From 5fc1788d375d95167218324e84853de4ba61fc50 Mon Sep 17 00:00:00 2001 From: Seth Rickard Date: Mon, 9 Jul 2018 15:28:41 -0500 Subject: [PATCH] [cc1352] add support for Texas Instruments CC1352 (#2863) --- configure.ac | 13 +- examples/Makefile-cc1352 | 293 ++ examples/Makefile-cc2652 | 2 +- examples/platforms/Makefile.am | 6 + examples/platforms/Makefile.platform.am | 4 + examples/platforms/cc1352/Makefile.am | 86 + .../platforms/cc1352/Makefile.platform.am | 44 + examples/platforms/cc1352/README.md | 120 + examples/platforms/cc1352/alarm.c | 130 + examples/platforms/cc1352/cc1352_ccfg.c | 49 + examples/platforms/cc1352/cc1352_radio.h | 201 ++ examples/platforms/cc1352/cc1352_startup.c | 39 + examples/platforms/cc1352/crypto/aes_alt.c | 202 ++ examples/platforms/cc1352/crypto/aes_alt.h | 111 + .../cc1352/crypto/cc1352-mbedtls-config.h | 2543 +++++++++++++++++ examples/platforms/cc1352/cxx_helpers.c | 54 + examples/platforms/cc1352/diag.c | 93 + examples/platforms/cc1352/flash.c | 313 ++ examples/platforms/cc1352/logging.c | 46 + examples/platforms/cc1352/misc.c | 92 + .../cc1352/openthread-core-cc1352-config.h | 64 + examples/platforms/cc1352/platform-cc1352.h | 89 + examples/platforms/cc1352/platform.c | 89 + examples/platforms/cc1352/radio.c | 1970 +++++++++++++ examples/platforms/cc1352/random.c | 139 + examples/platforms/cc1352/uart.c | 334 +++ examples/platforms/cc2650/diag.c | 9 +- examples/platforms/cc2650/misc.c | 1 - examples/platforms/cc2650/radio.c | 3 + examples/platforms/cc2652/Makefile.am | 74 +- .../platforms/cc2652/Makefile.platform.am | 14 +- examples/platforms/cc2652/cc2652_ccfg.c | 3 +- examples/platforms/cc2652/cc2652_radio.h | 32 +- .../cc2652/crypto/cc2652-mbedtls-config.h | 2 +- examples/platforms/cc2652/misc.c | 1 - examples/platforms/cc2652/radio.c | 39 +- examples/platforms/cc2652/uart.c | 2 +- include/openthread/platform/toolchain.h | 19 + tests/unit/Makefile.am | 1 + third_party/ti/README.md | 24 +- third_party/ti/devices/DeviceFamily.h | 146 +- .../{cc26x2 => cc13x2_cc26x2}/driverlib/adi.c | 0 .../{cc26x2 => cc13x2_cc26x2}/driverlib/adi.h | 0 .../driverlib/adi_doc.h | 0 .../{cc26x2 => cc13x2_cc26x2}/driverlib/aes.c | 171 +- .../{cc26x2 => cc13x2_cc26x2}/driverlib/aes.h | 248 +- .../driverlib/aes_doc.h | 4 +- .../driverlib/aon_batmon.c | 0 .../driverlib/aon_batmon.h | 0 .../driverlib/aon_event.c | 4 +- .../driverlib/aon_event.h | 10 +- .../driverlib/aon_event_doc.h | 11 +- .../driverlib/aon_ioc.c | 0 .../driverlib/aon_ioc.h | 0 .../driverlib/aon_ioc_doc.h | 0 .../driverlib/aon_pmctl.c | 4 +- .../driverlib/aon_pmctl.h | 35 +- .../driverlib/aon_pmctl_doc.h | 7 +- .../driverlib/aon_rtc.c | 4 +- .../driverlib/aon_rtc.h | 4 +- .../driverlib/aon_rtc_doc.h | 0 .../driverlib/aux_adc.c | 8 +- .../driverlib/aux_adc.h | 13 +- .../driverlib/aux_smph.c | 0 .../driverlib/aux_smph.h | 0 .../cc13x2_cc26x2/driverlib/aux_sysif.c | 96 + .../cc13x2_cc26x2/driverlib/aux_sysif.h | 154 + .../driverlib/aux_tdc.c | 0 .../driverlib/aux_tdc.h | 244 +- .../driverlib/bin/ccs/driverlib.lib | Bin 1494256 -> 1658276 bytes .../driverlib/bin/ccs/makedefs | 0 .../driverlib/bin/ccs/makefile | 4 +- .../driverlib/bin/gcc/driverlib.a | Bin 345810 -> 384530 bytes .../driverlib/bin/gcc/makedefs | 0 .../driverlib/bin/gcc/makefile | 4 +- .../driverlib/bin/iar/driverlib.lib | Bin 782906 -> 873144 bytes .../driverlib/bin/iar/makedefs | 0 .../driverlib/bin/iar/makefile | 5 +- .../driverlib/bin/keil/driverlib.lib | Bin 155160 -> 167772 bytes .../driverlib/bin/keil/makedefs | 0 .../driverlib/bin/keil/makefile | 4 +- .../driverlib/ccfgread.c | 0 .../driverlib/ccfgread.h | 0 .../driverlib/ccfgread_doc.h | 0 .../driverlib/chipinfo.c | 65 +- .../driverlib/chipinfo.h | 72 +- .../{cc26x2 => cc13x2_cc26x2}/driverlib/cpu.c | 52 +- .../{cc26x2 => cc13x2_cc26x2}/driverlib/cpu.h | 47 +- .../driverlib/cpu_doc.h | 0 .../driverlib/crypto.c | 10 +- .../driverlib/crypto.h | 29 +- .../{cc26x2 => cc13x2_cc26x2}/driverlib/ddi.c | 0 .../{cc26x2 => cc13x2_cc26x2}/driverlib/ddi.h | 0 .../driverlib/ddi_doc.h | 0 .../driverlib/debug.c | 0 .../driverlib/debug.h | 0 .../driverlib/driverlib_release.c | 2 +- .../driverlib/driverlib_release.h | 6 +- .../driverlib/event.c | 0 .../driverlib/event.h | 0 .../driverlib/event_doc.h | 0 .../driverlib/flash.c | 8 +- .../driverlib/flash.h | 50 +- .../driverlib/gpio.c | 0 .../driverlib/gpio.h | 23 +- .../driverlib/gpio_doc.h | 0 .../driverlib/group_analog_doc.h | 0 .../driverlib/group_aon_doc.h | 0 .../driverlib/group_aux_doc.h | 0 .../{cc26x2 => cc13x2_cc26x2}/driverlib/i2c.c | 0 .../{cc26x2 => cc13x2_cc26x2}/driverlib/i2c.h | 17 +- .../driverlib/i2c_doc.h | 0 .../{cc26x2 => cc13x2_cc26x2}/driverlib/i2s.c | 11 +- .../{cc26x2 => cc13x2_cc26x2}/driverlib/i2s.h | 19 +- .../driverlib/interrupt.c | 19 +- .../driverlib/interrupt.h | 392 ++- .../cc13x2_cc26x2/driverlib/interrupt_doc.h | 162 ++ .../{cc26x2 => cc13x2_cc26x2}/driverlib/ioc.c | 4 +- .../{cc26x2 => cc13x2_cc26x2}/driverlib/ioc.h | 19 +- .../driverlib/ioc_doc.h | 0 .../{cc26x2 => cc13x2_cc26x2}/driverlib/osc.c | 27 +- .../{cc26x2 => cc13x2_cc26x2}/driverlib/osc.h | 32 +- .../ti/devices/cc13x2_cc26x2/driverlib/pka.c | 1634 +++++++++++ .../ti/devices/cc13x2_cc26x2/driverlib/pka.h | 1441 ++++++++++ .../driverlib/pka_doc.h | 4 +- .../driverlib/prcm.c | 4 +- .../driverlib/prcm.h | 22 +- .../driverlib/pwr_ctrl.c | 4 +- .../driverlib/pwr_ctrl.h | 38 +- .../driverlib/rf_ble_cmd.h | 750 ++++- .../driverlib/rf_ble_mailbox.h | 9 +- .../driverlib/rf_common_cmd.h | 186 +- .../driverlib/rf_data_entry.h | 26 +- .../cc13x2_cc26x2/driverlib/rf_hs_cmd.h | 210 ++ .../cc13x2_cc26x2/driverlib/rf_hs_mailbox.h | 65 + .../driverlib/rf_ieee_cmd.h | 52 +- .../driverlib/rf_ieee_mailbox.h | 9 +- .../driverlib/rf_mailbox.h | 335 +-- .../driverlib/rf_prop_cmd.h | 303 +- .../cc13x2_cc26x2/driverlib/rf_prop_mailbox.h | 71 + .../{cc26x2 => cc13x2_cc26x2}/driverlib/rfc.c | 188 +- .../{cc26x2 => cc13x2_cc26x2}/driverlib/rfc.h | 439 ++- .../{cc26x2 => cc13x2_cc26x2}/driverlib/rom.h | 8 +- .../driverlib/setup.c | 104 +- .../driverlib/setup.h | 0 .../cc13x2_cc26x2/driverlib/setup_doc.h | 41 + .../driverlib/setup_rom.c | 56 +- .../driverlib/setup_rom.h | 6 +- .../cc13x2_cc26x2/driverlib/setup_rom_doc.h | 44 + .../driverlib/sha2.c | 71 +- .../driverlib/sha2.h | 110 +- .../driverlib/sha2_doc.h | 6 +- .../driverlib/smph.c | 0 .../driverlib/smph.h | 0 .../driverlib/smph_doc.h | 0 .../{cc26x2 => cc13x2_cc26x2}/driverlib/ssi.c | 0 .../{cc26x2 => cc13x2_cc26x2}/driverlib/ssi.h | 17 +- .../driverlib/sw_chacha.c | 0 .../driverlib/sw_ecrypt-config.h | 0 .../driverlib/sw_ecrypt-machine.h | 0 .../driverlib/sw_ecrypt-portable.h | 0 .../driverlib/sw_ecrypt-sync.h | 0 .../driverlib/sw_poly1305-donna-32.h | 0 .../driverlib/sw_poly1305-donna.c | 0 .../driverlib/sw_poly1305-donna.h | 0 .../cc13x2_cc26x2/driverlib/sys_ctrl.c | 380 +++ .../driverlib/sys_ctrl.h | 251 +- .../driverlib/systick.c | 0 .../driverlib/systick.h | 13 +- .../driverlib/systick_doc.h | 0 .../driverlib/timer.c | 0 .../driverlib/timer.h | 21 +- .../driverlib/timer_doc.h | 0 .../driverlib/trng.c | 0 .../driverlib/trng.h | 19 +- .../driverlib/uart.c | 4 +- .../driverlib/uart.h | 23 +- .../cc13x2_cc26x2/driverlib/uart_doc.h | 107 + .../driverlib/udma.c | 0 .../driverlib/udma.h | 36 +- .../driverlib/vims.c | 17 +- .../driverlib/vims.h | 0 .../driverlib/watchdog.c | 0 .../driverlib/watchdog.h | 17 +- .../cc13x2_cc26x2/driverlib/watchdog_doc.h | 121 + .../{cc26x2 => cc13x2_cc26x2}/inc/asmdefs.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_adi.h | 0 .../inc/hw_adi_2_refsys.h | 0 .../inc/hw_adi_3_refsys.h | 0 .../inc/hw_adi_4_aux.h | 0 .../inc/hw_aon_batmon.h | 24 +- .../inc/hw_aon_event.h | 0 .../inc/hw_aon_ioc.h | 4 +- .../inc/hw_aon_pmctl.h | 53 +- .../inc/hw_aon_rtc.h | 0 .../inc/hw_aux_aiodio.h | 10 +- .../inc/hw_aux_anaif.h | 48 +- .../inc/hw_aux_evctl.h | 20 +- .../inc/hw_aux_mac.h | 0 .../inc/hw_aux_ram.h | 4 +- .../inc/hw_aux_sce.h | 0 .../inc/hw_aux_smph.h | 0 .../inc/hw_aux_spim.h | 12 +- .../inc/hw_aux_sysif.h | 0 .../inc/hw_aux_tdc.h | 80 +- .../inc/hw_aux_timer01.h | 98 +- .../inc/hw_aux_timer2.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_ccfg.h | 0 .../inc/hw_ccfg_simple_struct.h | 0 .../inc/hw_chip_def.h | 48 +- .../inc/hw_cpu_dwt.h | 0 .../inc/hw_cpu_fpb.h | 0 .../inc/hw_cpu_itm.h | 0 .../inc/hw_cpu_rom_table.h | 0 .../inc/hw_cpu_scs.h | 0 .../inc/hw_cpu_tiprop.h | 0 .../inc/hw_cpu_tpiu.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_crypto.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_ddi.h | 4 +- .../inc/hw_ddi_0_osc.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_event.h | 581 ++-- .../{cc26x2 => cc13x2_cc26x2}/inc/hw_fcfg1.h | 311 +- .../{cc26x2 => cc13x2_cc26x2}/inc/hw_flash.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_gpio.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_gpram.h | 4 +- .../{cc26x2 => cc13x2_cc26x2}/inc/hw_gpt.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_i2c.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_i2s.h | 27 +- .../{cc26x2 => cc13x2_cc26x2}/inc/hw_ints.h | 6 +- .../{cc26x2 => cc13x2_cc26x2}/inc/hw_ioc.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_memmap.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_nvic.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_pka.h | 6 +- .../inc/hw_pka_int.h | 0 .../inc/hw_pka_ram.h | 4 +- .../{cc26x2 => cc13x2_cc26x2}/inc/hw_prcm.h | 6 +- .../inc/hw_rfc_dbell.h | 90 +- .../inc/hw_rfc_pwr.h | 0 .../ti/devices/cc13x2_cc26x2/inc/hw_rfc_rat.h | 198 ++ .../inc/hw_rfc_ullram.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_smph.h | 0 .../inc/hw_sram_mmr.h | 23 +- .../{cc26x2 => cc13x2_cc26x2}/inc/hw_ssi.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_sysctl.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_trng.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_types.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_uart.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_udma.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_vims.h | 0 .../{cc26x2 => cc13x2_cc26x2}/inc/hw_wdt.h | 0 .../linker_files/cc26x2r1f.cmd | 0 .../linker_files/cc26x2r1f.icf | 0 .../linker_files/cc26x2r1f.lds | 12 +- .../linker_files/cc26x2r1f.sct | 0 .../linker_files/cc26x2r1f_ram.icf | 143 + .../rf_patches/rf_patch_cpe_ble.h | 321 +++ .../rf_patches/rf_patch_cpe_bt5.h | 651 +++++ .../rf_patches/rf_patch_cpe_ieee_802_15_4.h | 284 ++ .../rf_patches/rf_patch_cpe_multi_protocol.h | 808 ++++++ .../rf_patches/rf_patch_cpe_prop.h | 514 ++++ .../rf_patches/rf_patch_mce_bt5.h | 623 ++++ .../rf_patches/rf_patch_mce_genfsk.h | 591 ++++ .../rf_patches/rf_patch_mce_ieee_802_15_4.h | 479 ++++ .../rf_patches/rf_patch_mce_sl_longrange.h | 335 +++ .../rf_patches/rf_patch_mce_slr.h | 365 +++ .../rf_patches/rf_patch_rfe_bt5.h | 610 ++++ .../rf_patches/rf_patch_rfe_genfsk.h | 611 ++++ .../rf_patches/rf_patch_rfe_ieee_802_15_4.h | 438 +++ .../{cc26x2 => cc13x2_cc26x2}/rom/driverlib.c | 2 +- .../rom/driverlib.elf | Bin .../{cc26x2 => cc13x2_cc26x2}/rom/readme.txt | 0 .../startup_files/ccfg.c | 166 +- .../startup_files/startup_ccs.c | 0 .../startup_files/startup_gcc.c | 14 +- .../startup_files/startup_iar.c | 0 .../startup_files/startup_keil.s | 0 .../ti/devices/cc26x0/driverlib/aon_event.c | 4 +- .../ti/devices/cc26x0/driverlib/aon_event.h | 4 +- .../devices/cc26x0/driverlib/aon_event_doc.h | 4 +- .../ti/devices/cc26x0/driverlib/aon_rtc.c | 4 +- .../ti/devices/cc26x0/driverlib/aon_rtc.h | 4 +- .../ti/devices/cc26x0/driverlib/aon_wuc.c | 4 +- .../ti/devices/cc26x0/driverlib/aon_wuc.h | 4 +- .../ti/devices/cc26x0/driverlib/aux_adc.c | 4 +- .../ti/devices/cc26x0/driverlib/aux_tdc.h | 116 +- .../ti/devices/cc26x0/driverlib/aux_timer.c | 4 +- .../ti/devices/cc26x0/driverlib/aux_timer.h | 4 +- .../ti/devices/cc26x0/driverlib/aux_wuc.c | 4 +- .../ti/devices/cc26x0/driverlib/aux_wuc.h | 4 +- .../cc26x0/driverlib/bin/ccs/driverlib.lib | Bin 1420040 -> 1430384 bytes .../cc26x0/driverlib/bin/gcc/driverlib.a | Bin 371372 -> 372640 bytes .../cc26x0/driverlib/bin/iar/driverlib.lib | Bin 767860 -> 783088 bytes .../cc26x0/driverlib/bin/keil/driverlib.lib | Bin 146270 -> 146282 bytes .../ti/devices/cc26x0/driverlib/chipinfo.c | 4 +- .../ti/devices/cc26x0/driverlib/chipinfo.h | 54 +- third_party/ti/devices/cc26x0/driverlib/cpu.h | 4 +- .../ti/devices/cc26x0/driverlib/crypto.h | 19 +- .../cc26x0/driverlib/driverlib_release.c | 2 +- .../cc26x0/driverlib/driverlib_release.h | 6 +- .../ti/devices/cc26x0/driverlib/flash.c | 4 +- .../ti/devices/cc26x0/driverlib/flash.h | 19 +- third_party/ti/devices/cc26x0/driverlib/i2c.h | 17 +- third_party/ti/devices/cc26x0/driverlib/i2s.c | 11 +- third_party/ti/devices/cc26x0/driverlib/i2s.h | 19 +- .../ti/devices/cc26x0/driverlib/interrupt.c | 19 +- .../ti/devices/cc26x0/driverlib/interrupt.h | 369 ++- .../devices/cc26x0/driverlib/interrupt_doc.h | 136 +- third_party/ti/devices/cc26x0/driverlib/ioc.c | 4 +- third_party/ti/devices/cc26x0/driverlib/ioc.h | 17 +- third_party/ti/devices/cc26x0/driverlib/osc.c | 4 +- third_party/ti/devices/cc26x0/driverlib/osc.h | 4 +- .../ti/devices/cc26x0/driverlib/prcm.c | 4 +- .../ti/devices/cc26x0/driverlib/prcm.h | 14 +- .../ti/devices/cc26x0/driverlib/pwr_ctrl.c | 4 +- .../ti/devices/cc26x0/driverlib/pwr_ctrl.h | 4 +- .../ti/devices/cc26x0/driverlib/rf_ble_cmd.h | 6 +- .../devices/cc26x0/driverlib/rf_ble_mailbox.h | 4 +- .../ti/devices/cc26x0/driverlib/rf_ieee_cmd.h | 10 +- .../cc26x0/driverlib/rf_ieee_mailbox.h | 4 +- .../ti/devices/cc26x0/driverlib/rf_mailbox.h | 4 +- .../cc26x0/driverlib/rf_prop_mailbox.h | 6 +- third_party/ti/devices/cc26x0/driverlib/rfc.c | 4 +- third_party/ti/devices/cc26x0/driverlib/rom.h | 4 + .../ti/devices/cc26x0/driverlib/setup.c | 5 +- .../ti/devices/cc26x0/driverlib/setup_rom.c | 4 +- .../ti/devices/cc26x0/driverlib/setup_rom.h | 4 +- third_party/ti/devices/cc26x0/driverlib/ssi.h | 17 +- .../ti/devices/cc26x0/driverlib/sys_ctrl.c | 17 +- .../ti/devices/cc26x0/driverlib/sys_ctrl.h | 12 +- .../ti/devices/cc26x0/driverlib/systick.h | 13 +- .../ti/devices/cc26x0/driverlib/timer.h | 21 +- .../ti/devices/cc26x0/driverlib/trng.h | 19 +- .../ti/devices/cc26x0/driverlib/uart.c | 4 +- .../ti/devices/cc26x0/driverlib/uart.h | 23 +- .../ti/devices/cc26x0/driverlib/udma.h | 36 +- .../ti/devices/cc26x0/driverlib/vims.c | 4 +- .../ti/devices/cc26x0/driverlib/watchdog.h | 17 +- .../ti/devices/cc26x0/inc/hw_aux_aiodio.h | 380 ++- .../ti/devices/cc26x0/inc/hw_aux_anaif.h | 160 +- .../ti/devices/cc26x0/inc/hw_aux_evctl.h | 812 +++--- .../ti/devices/cc26x0/inc/hw_aux_smph.h | 138 +- .../ti/devices/cc26x0/inc/hw_aux_tdc.h | 543 ++-- .../ti/devices/cc26x0/inc/hw_aux_timer.h | 292 +- .../ti/devices/cc26x0/inc/hw_chip_def.h | 45 +- third_party/ti/devices/cc26x0/inc/hw_ddi.h | 4 +- third_party/ti/devices/cc26x0/inc/hw_device.h | 4 +- .../cc26x0/linker_files/cc26x0f128.cmd | 2 +- .../cc26x0/linker_files/cc26x0f128.icf | 2 +- .../cc26x0/linker_files/cc26x0f128.lds | 2 +- .../cc26x0/linker_files/cc26x0f128.sct | 2 +- .../cc26x0/rf_patches/rf_patch_cpe_ble.h | 2 +- .../rf_patches/rf_patch_cpe_ble_priv_1_2.h | 2 +- .../cc26x0/rf_patches/rf_patch_cpe_genfsk.h | 2 +- .../cc26x0/rf_patches/rf_patch_cpe_ieee.h | 4 +- .../cc26x0/rf_patches/rf_patch_mce_genfsk.h | 2 +- .../cc26x0/rf_patches/rf_patch_mce_ieee_s.h | 4 +- .../cc26x0/rf_patches/rf_patch_rfe_ble.h | 2 +- .../cc26x0/rf_patches/rf_patch_rfe_genfsk.h | 2 +- .../cc26x0/rf_patches/rf_patch_rfe_ieee_s.h | 4 +- .../ti/devices/cc26x0/startup_files/ccfg.c | 127 +- .../cc26x0/startup_files/startup_ccs.c | 2 +- .../cc26x0/startup_files/startup_gcc.c | 2 +- .../cc26x0/startup_files/startup_iar.c | 2 +- .../cc26x0/startup_files/startup_keil.s | 2 +- .../devices/cc26x2/driverlib/interrupt_doc.h | 146 - third_party/ti/devices/cc26x2/driverlib/pka.c | 722 ----- third_party/ti/devices/cc26x2/driverlib/pka.h | 655 ----- .../cc26x2/driverlib/rf_prop_mailbox.h | 98 - .../ti/devices/cc26x2/driverlib/sys_ctrl.c | 173 -- .../devices/cc26x2/driverlib/watchdog_doc.h | 98 - third_party/ti/devices/cc26x2/inc/hw_device.h | 168 -- .../ti/devices/cc26x2/inc/hw_rfc_rat.h | 62 - ...release_notes_driverlib_cc13xx_cc26xx.html | 190 ++ ...tml => ti-openthread_1.01.0_manifest.html} | 1098 ++++--- 374 files changed, 26121 insertions(+), 6460 deletions(-) create mode 100644 examples/Makefile-cc1352 create mode 100644 examples/platforms/cc1352/Makefile.am create mode 100644 examples/platforms/cc1352/Makefile.platform.am create mode 100644 examples/platforms/cc1352/README.md create mode 100644 examples/platforms/cc1352/alarm.c create mode 100644 examples/platforms/cc1352/cc1352_ccfg.c create mode 100644 examples/platforms/cc1352/cc1352_radio.h create mode 100644 examples/platforms/cc1352/cc1352_startup.c create mode 100644 examples/platforms/cc1352/crypto/aes_alt.c create mode 100644 examples/platforms/cc1352/crypto/aes_alt.h create mode 100644 examples/platforms/cc1352/crypto/cc1352-mbedtls-config.h create mode 100644 examples/platforms/cc1352/cxx_helpers.c create mode 100644 examples/platforms/cc1352/diag.c create mode 100644 examples/platforms/cc1352/flash.c create mode 100644 examples/platforms/cc1352/logging.c create mode 100644 examples/platforms/cc1352/misc.c create mode 100644 examples/platforms/cc1352/openthread-core-cc1352-config.h create mode 100644 examples/platforms/cc1352/platform-cc1352.h create mode 100644 examples/platforms/cc1352/platform.c create mode 100644 examples/platforms/cc1352/radio.c create mode 100644 examples/platforms/cc1352/random.c create mode 100644 examples/platforms/cc1352/uart.c rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/adi.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/adi.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/adi_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aes.c (60%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aes.h (73%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aes_doc.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_batmon.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_batmon.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_event.c (98%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_event.h (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_event_doc.h (83%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_ioc.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_ioc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_ioc_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_pmctl.c (95%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_pmctl.h (86%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_pmctl_doc.h (95%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_rtc.c (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_rtc.h (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aon_rtc_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aux_adc.c (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aux_adc.h (96%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aux_smph.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aux_smph.h (100%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_sysif.c create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_sysif.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aux_tdc.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/aux_tdc.h (78%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/ccs/driverlib.lib (58%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/ccs/makedefs (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/ccs/makefile (92%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/gcc/driverlib.a (59%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/gcc/makedefs (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/gcc/makefile (92%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/iar/driverlib.lib (54%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/iar/makedefs (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/iar/makefile (93%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/keil/driverlib.lib (58%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/keil/makedefs (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/bin/keil/makefile (90%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ccfgread.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ccfgread.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ccfgread_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/chipinfo.c (72%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/chipinfo.h (87%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/cpu.c (91%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/cpu.h (89%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/cpu_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/crypto.c (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/crypto.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ddi.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ddi.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ddi_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/debug.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/debug.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/driverlib_release.c (98%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/driverlib_release.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/event.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/event.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/event_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/flash.c (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/flash.h (94%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/gpio.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/gpio.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/gpio_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/group_analog_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/group_aon_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/group_aux_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/i2c.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/i2c.h (98%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/i2c_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/i2s.c (96%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/i2s.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/interrupt.c (96%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/interrupt.h (57%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/interrupt_doc.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ioc.c (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ioc.h (98%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ioc_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/osc.c (94%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/osc.h (93%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/pka.c create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/pka.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/pka_doc.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/prcm.c (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/prcm.h (98%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/pwr_ctrl.c (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/pwr_ctrl.h (90%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rf_ble_cmd.h (77%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rf_ble_mailbox.h (95%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rf_common_cmd.h (88%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rf_data_entry.h (96%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/rf_hs_cmd.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/rf_hs_mailbox.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rf_ieee_cmd.h (98%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rf_ieee_mailbox.h (94%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rf_mailbox.h (57%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rf_prop_cmd.h (76%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/rf_prop_mailbox.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rfc.c (55%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rfc.h (63%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/rom.h (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/setup.c (81%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/setup.h (100%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/setup_doc.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/setup_rom.c (95%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/setup_rom.h (99%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/setup_rom_doc.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sha2.c (79%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sha2.h (88%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sha2_doc.h (94%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/smph.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/smph.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/smph_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ssi.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/ssi.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sw_chacha.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sw_ecrypt-config.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sw_ecrypt-machine.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sw_ecrypt-portable.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sw_ecrypt-sync.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sw_poly1305-donna-32.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sw_poly1305-donna.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sw_poly1305-donna.h (100%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/sys_ctrl.c rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/sys_ctrl.h (55%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/systick.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/systick.h (95%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/systick_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/timer.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/timer.h (98%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/timer_doc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/trng.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/trng.h (96%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/uart.c (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/uart.h (98%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/uart_doc.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/udma.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/udma.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/vims.c (88%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/vims.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/watchdog.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/driverlib/watchdog.h (97%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/driverlib/watchdog_doc.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/asmdefs.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_adi.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_adi_2_refsys.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_adi_3_refsys.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_adi_4_aux.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aon_batmon.h (96%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aon_event.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aon_ioc.h (98%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aon_pmctl.h (94%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aon_rtc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_aiodio.h (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_anaif.h (94%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_evctl.h (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_mac.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_ram.h (95%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_sce.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_smph.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_spim.h (96%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_sysif.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_tdc.h (94%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_timer01.h (91%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_aux_timer2.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_ccfg.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_ccfg_simple_struct.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_chip_def.h (82%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_cpu_dwt.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_cpu_fpb.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_cpu_itm.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_cpu_rom_table.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_cpu_scs.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_cpu_tiprop.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_cpu_tpiu.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_crypto.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_ddi.h (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_ddi_0_osc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_event.h (90%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_fcfg1.h (90%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_flash.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_gpio.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_gpram.h (95%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_gpt.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_i2c.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_i2s.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_ints.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_ioc.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_memmap.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_nvic.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_pka.h (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_pka_int.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_pka_ram.h (95%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_prcm.h (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_rfc_dbell.h (97%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_rfc_pwr.h (100%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/inc/hw_rfc_rat.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_rfc_ullram.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_smph.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_sram_mmr.h (86%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_ssi.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_sysctl.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_trng.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_types.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_uart.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_udma.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_vims.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/inc/hw_wdt.h (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/linker_files/cc26x2r1f.cmd (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/linker_files/cc26x2r1f.icf (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/linker_files/cc26x2r1f.lds (93%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/linker_files/cc26x2r1f.sct (100%) create mode 100644 third_party/ti/devices/cc13x2_cc26x2/linker_files/cc26x2r1f_ram.icf create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_cpe_ble.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_cpe_bt5.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_cpe_ieee_802_15_4.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_cpe_multi_protocol.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_cpe_prop.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_mce_bt5.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_mce_genfsk.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_mce_ieee_802_15_4.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_mce_sl_longrange.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_mce_slr.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_rfe_bt5.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_rfe_genfsk.h create mode 100644 third_party/ti/devices/cc13x2_cc26x2/rf_patches/rf_patch_rfe_ieee_802_15_4.h rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/rom/driverlib.c (99%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/rom/driverlib.elf (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/rom/readme.txt (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/startup_files/ccfg.c (61%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/startup_files/startup_ccs.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/startup_files/startup_gcc.c (96%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/startup_files/startup_iar.c (100%) rename third_party/ti/devices/{cc26x2 => cc13x2_cc26x2}/startup_files/startup_keil.s (100%) delete mode 100644 third_party/ti/devices/cc26x2/driverlib/interrupt_doc.h delete mode 100644 third_party/ti/devices/cc26x2/driverlib/pka.c delete mode 100644 third_party/ti/devices/cc26x2/driverlib/pka.h delete mode 100644 third_party/ti/devices/cc26x2/driverlib/rf_prop_mailbox.h delete mode 100644 third_party/ti/devices/cc26x2/driverlib/sys_ctrl.c delete mode 100644 third_party/ti/devices/cc26x2/driverlib/watchdog_doc.h delete mode 100644 third_party/ti/devices/cc26x2/inc/hw_device.h delete mode 100644 third_party/ti/devices/cc26x2/inc/hw_rfc_rat.h rename third_party/ti/{ti-openthread_0.9.0_manifest.html => ti-openthread_1.01.0_manifest.html} (61%) diff --git a/configure.ac b/configure.ac index 54d8eaffc..b9e940230 100644 --- a/configure.ac +++ b/configure.ac @@ -1381,12 +1381,12 @@ AM_CONDITIONAL([OPENTHREAD_ENABLE_LINKER_MAP], [test "${enable_linker_map}" = "y AC_ARG_WITH(examples, [AS_HELP_STRING([--with-examples=TARGET], - [Specify the examples from one of: none, posix, cc2538, cc2650, cc2652, da15000, efr32, emsk, gp712, kw41z, nrf52840, samr21 @<:@default=none@:>@.])], + [Specify the examples from one of: none, posix, cc1352, cc2538, cc2650, cc2652, da15000, efr32, emsk, gp712, kw41z, nrf52840, samr21 @<:@default=none@:>@.])], [ case "${with_examples}" in none) ;; - posix|cc2538|cc2650|cc2652|da15000|efr32|emsk|gp712|kw41z|nrf52840|samr21) + posix|cc1352|cc2538|cc2650|cc2652|da15000|efr32|emsk|gp712|kw41z|nrf52840|samr21) if test ${enable_posix_app} = "yes"; then AC_MSG_ERROR([--with-examples must be none when POSIX apps are enabled by --enable-posix-app]) fi @@ -1407,6 +1407,11 @@ case ${with_examples} in AC_DEFINE_UNQUOTED([OPENTHREAD_EXAMPLES_POSIX],[${OPENTHREAD_EXAMPLES_POSIX}],[Define to 1 if you want to use posix examples]) ;; + cc1352) + OPENTHREAD_EXAMPLES_CC1352=1 + AC_DEFINE_UNQUOTED([OPENTHREAD_EXAMPLES_CC1352],[${OPENTHREAD_EXAMPLES_CC1352}],[Define to 1 if you want to use cc1352 examples]) + ;; + cc2538) OPENTHREAD_EXAMPLES_CC2538=1 AC_DEFINE_UNQUOTED([OPENTHREAD_EXAMPLES_CC2538],[${OPENTHREAD_EXAMPLES_CC2538}],[Define to 1 if you want to use cc2538 examples]) @@ -1469,6 +1474,9 @@ AC_DEFINE_UNQUOTED([OPENTHREAD_EXAMPLES],[${OPENTHREAD_EXAMPLES}],[OpenThread ex AC_SUBST(OPENTHREAD_EXAMPLES_POSIX) AM_CONDITIONAL([OPENTHREAD_EXAMPLES_POSIX], [test "${OPENTHREAD_EXAMPLES}" = "posix"]) +AC_SUBST(OPENTHREAD_EXAMPLES_CC1352) +AM_CONDITIONAL([OPENTHREAD_EXAMPLES_CC1352], [test "${OPENTHREAD_EXAMPLES}" = "cc1352"]) + AC_SUBST(OPENTHREAD_EXAMPLES_CC2538) AM_CONDITIONAL([OPENTHREAD_EXAMPLES_CC2538], [test "${OPENTHREAD_EXAMPLES}" = "cc2538"]) @@ -1641,6 +1649,7 @@ examples/apps/Makefile examples/apps/cli/Makefile examples/apps/ncp/Makefile examples/platforms/Makefile +examples/platforms/cc1352/Makefile examples/platforms/cc2538/Makefile examples/platforms/cc2650/Makefile examples/platforms/cc2652/Makefile diff --git a/examples/Makefile-cc1352 b/examples/Makefile-cc1352 new file mode 100644 index 000000000..6ab371fc0 --- /dev/null +++ b/examples/Makefile-cc1352 @@ -0,0 +1,293 @@ +# +# Copyright (c) 2018, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. +# + +.NOTPARALLEL: + +AR = arm-none-eabi-ar +CCAS = arm-none-eabi-as +CPP = arm-none-eabi-cpp +CC = arm-none-eabi-gcc +CXX = arm-none-eabi-g++ +LD = arm-none-eabi-ld +STRIP = arm-none-eabi-strip +NM = arm-none-eabi-nm +RANLIB = arm-none-eabi-ranlib +OBJCOPY = arm-none-eabi-objcopy + +BuildJobs ?= 10 + +configure_OPTIONS = \ + --enable-cli-app=all \ + --enable-ncp-app=all \ + --with-ncp-bus=uart \ + --enable-diag \ + --with-examples=cc1352 \ + MBEDTLS_CPPFLAGS="$(CC1352_MBEDTLS_CPPFLAGS)" \ + $(NULL) + +DEFAULT_LOGGING ?= 1 + +CC1352_MBEDTLS_CPPFLAGS = \ + -DMBEDTLS_CONFIG_FILE='\"cc1352-mbedtls-config.h\"' \ + -I$(PWD)/examples/platforms/cc1352/crypto \ + -I$(PWD)/third_party/ti/devices/cc13x2_cc26x2 \ + -I$(PWD)/third_party/mbedtls \ + -I$(PWD)/third_party/mbedtls/repo/include \ + $(NULL) + +CC1352_CONFIG_FILE_CPPFLAGS = \ + -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-cc1352-config.h\"' \ + -I$(PWD)/examples/platforms/cc1352/ \ + $(NULL) + +COMMONCFLAGS := \ + -fdata-sections \ + -ffunction-sections \ + -Os \ + -g \ + $(CC1352_CONFIG_FILE_CPPFLAGS) \ + $(NULL) + +include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk + +CPPFLAGS += \ + $(COMMONCFLAGS) \ + $(target_CPPFLAGS) \ + $(NULL) + +CFLAGS += \ + $(COMMONCFLAGS) \ + $(target_CFLAGS) \ + $(NULL) + +CXXFLAGS += \ + $(COMMONCFLAGS) \ + $(target_CXXFLAGS) \ + -fno-exceptions \ + -fno-rtti \ + $(NULL) + +LDFLAGS += \ + $(COMMONCFLAGS) \ + $(target_LDFLAGS) \ + -nostartfiles \ + -specs=nano.specs \ + -specs=nosys.specs \ + -Wl,--gc-sections \ + -Wl,-Map=map.map \ + $(NULL) + +ECHO := @echo +MAKE := make +MKDIR_P := mkdir -p +LN_S := ln -s +RM_F := rm -f + +INSTALL := /usr/bin/install +INSTALLFLAGS := -p + +TopSourceDir := $(dir $(shell readlink $(firstword $(MAKEFILE_LIST)))).. +AbsTopSourceDir := $(dir $(realpath $(firstword $(MAKEFILE_LIST)))).. + +BuildPath = build +TopBuildDir = $(BuildPath) +AbsTopBuildDir = $(PWD)/$(TopBuildDir) + +ResultPath = output +TopResultDir = $(ResultPath) +AbsTopResultDir = $(PWD)/$(TopResultDir) + +TargetTuple = cc1352 + +ARCHS = cortex-m4f + +TopTargetLibDir = $(TopResultDir)/$(TargetTuple)/lib + +ifndef BuildJobs +BuildJobs := $(shell getconf _NPROCESSORS_ONLN) +endif +JOBSFLAG := -j$(BuildJobs) + +# +# configure-arch +# +# Configure OpenThread for the specified architecture. +# +# arch - The architecture to configure. +# +define configure-arch +$(ECHO) " CONFIG $(TargetTuple)..." +(cd $(BuildPath)/$(TargetTuple) \ + && $(AbsTopSourceDir)/configure \ + INSTALL="$(INSTALL) $(INSTALLFLAGS)" \ + CPP="$(CPP)" \ + CC="$(CC)" \ + CXX="$(CXX)" \ + OBJC="$(OBJC)" \ + OBJCXX="$(OBJCXX)" \ + AR="$(AR)" \ + RANLIB="$(RANLIB)" \ + NM="$(NM)" \ + STRIP="$(STRIP)" \ + CPPFLAGS="$(CPPFLAGS)" \ + CFLAGS="$(CFLAGS)" \ + CXXFLAGS="$(CXXFLAGS)" \ + LDFLAGS="$(LDFLAGS)" \ + --host=arm-none-eabi \ + --prefix=/ \ + --exec-prefix=/$(TargetTuple) \ + $(configure_OPTIONS)) +endef # configure-arch + +# +# build-arch +# +# Build the OpenThread intermediate build products for the specified +# architecture. +# +# arch - The architecture to build. +# +define build-arch +$(ECHO) " BUILD $(TargetTuple)" +$(MAKE) \ + $(JOBSFLAG) \ + -C $(BuildPath)/$(TargetTuple) \ + --no-print-directory \ + all +endef # build-arch + +# +# stage-arch +# +# Stage (install) the OpenThread final build products for the specified +# architecture. +# +# arch - The architecture to stage. +# +define stage-arch +$(ECHO) " STAGE $(TargetTuple)" +$(MAKE) \ + $(JOBSFLAG) \ + -C $(BuildPath)/$(TargetTuple) \ + --no-print-directory \ + DESTDIR=$(AbsTopResultDir) \ + install +endef # stage-arch + +# +# ARCH_template +# +# Define macros, targets and rules to configure, build, and stage the +# OpenThread for a single architecture. +# +# arch - The architecture to instantiate the template for. +# +define ARCH_template +CONFIGURE_TARGETS += configure-$(1) +BUILD_TARGETS += do-build-$(1) +STAGE_TARGETS += stage-$(1) +BUILD_DIRS += $(BuildPath)/$(TargetTuple) +DIRECTORIES += $(BuildPath)/$(TargetTuple) + +configure-$(1): target_CPPFLAGS=$($(1)_target_CPPFLAGS) +configure-$(1): target_CFLAGS=$($(1)_target_CFLAGS) +configure-$(1): target_CXXFLAGS=$($(1)_target_CXXFLAGS) +configure-$(1): target_LDFLAGS=$($(1)_target_LDFLAGS) + +configure-$(1): $(BuildPath)/$(TargetTuple)/config.status + +$(BuildPath)/$(TargetTuple)/config.status: | $(BuildPath)/$(TargetTuple) + $$(call configure-arch,$(1)) + +do-build-$(1): configure-$(1) + +do-build-$(1): + +$$(call build-arch,$(1)) + +stage-$(1): do-build-$(1) + +stage-$(1): | $(TopResultDir) + $$(call stage-arch,$(1)) + +$(1): stage-$(1) +endef # ARCH_template + +.DEFAULT_GOAL := all + +all: stage + +# +# cortex-m4f +# + +cortex-m4f_target_ABI = cortex-m4f +cortex-m4f_target_CPPFLAGS = -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb +cortex-m4f_target_CFLAGS = -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb +cortex-m4f_target_CXXFLAGS = -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb +cortex-m4f_target_LDFLAGS = -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb + +# Instantiate an architecture-specific build template for each target +# architecture. + +$(foreach arch,$(ARCHS),$(eval $(call ARCH_template,$(arch)))) + +# +# Common / Finalization +# + +configure: $(CONFIGURE_TARGETS) + +build: $(BUILD_TARGETS) + +stage: $(STAGE_TARGETS) + +DIRECTORIES = $(TopResultDir) $(TopResultDir)/$(TargetTuple)/lib $(BUILD_DIRS) + +CLEAN_DIRS = $(TopResultDir) $(BUILD_DIRS) + +all: stage + +$(DIRECTORIES): + $(ECHO) " MKDIR $@" + @$(MKDIR_P) "$@" + +clean: + $(ECHO) " CLEAN" + @$(RM_F) -r $(CLEAN_DIRS) + +help: + $(ECHO) "Simply type 'make -f $(firstword $(MAKEFILE_LIST))' to build OpenThread for the following " + $(ECHO) "architectures: " + $(ECHO) "" + $(ECHO) " $(ARCHS)" + $(ECHO) "" + $(ECHO) "To build only a particular architecture, specify: " + $(ECHO) "" + $(ECHO) " make -f $(firstword $(MAKEFILE_LIST)) " + $(ECHO) "" + diff --git a/examples/Makefile-cc2652 b/examples/Makefile-cc2652 index e399e9b43..970f2929d 100644 --- a/examples/Makefile-cc2652 +++ b/examples/Makefile-cc2652 @@ -55,7 +55,7 @@ DEFAULT_LOGGING ?= 1 CC2652_MBEDTLS_CPPFLAGS = \ -DMBEDTLS_CONFIG_FILE='\"cc2652-mbedtls-config.h\"' \ -I$(PWD)/examples/platforms/cc2652/crypto \ - -I$(PWD)/third_party/ti/devices/cc26x2 \ + -I$(PWD)/third_party/ti/devices/cc13x2_cc26x2 \ -I$(PWD)/third_party/mbedtls \ -I$(PWD)/third_party/mbedtls/repo/include \ $(NULL) diff --git a/examples/platforms/Makefile.am b/examples/platforms/Makefile.am index fb2641d3c..69b281e15 100644 --- a/examples/platforms/Makefile.am +++ b/examples/platforms/Makefile.am @@ -31,6 +31,7 @@ include $(abs_top_nlbuild_autotools_dir)/automake/pre.am # Always package (e.g. for 'make dist') these subdirectories. DIST_SUBDIRS = \ + cc1352 \ cc2538 \ cc2650 \ cc2652 \ @@ -51,6 +52,10 @@ SUBDIRS = \ utils \ $(NULL) +if OPENTHREAD_EXAMPLES_CC1352 +SUBDIRS += cc1352 +endif + if OPENTHREAD_EXAMPLES_CC2538 SUBDIRS += cc2538 endif @@ -102,6 +107,7 @@ noinst_HEADERS = \ # Always pretty (e.g. for 'make pretty') these subdirectories. PRETTY_SUBDIRS = \ + cc1352 \ cc2538 \ cc2650 \ cc2652 \ diff --git a/examples/platforms/Makefile.platform.am b/examples/platforms/Makefile.platform.am index 8a389750b..8a005e1df 100644 --- a/examples/platforms/Makefile.platform.am +++ b/examples/platforms/Makefile.platform.am @@ -41,6 +41,10 @@ LDFLAGS_COMMON = $(NULL) SOURCES_COMMON = $(NULL) LIBTOOLFLAGS_COMMON = --preserve-dup-deps +if OPENTHREAD_EXAMPLES_CC1352 +include $(top_srcdir)/examples/platforms/cc1352/Makefile.platform.am +endif + if OPENTHREAD_EXAMPLES_CC2538 include $(top_srcdir)/examples/platforms/cc2538/Makefile.platform.am endif diff --git a/examples/platforms/cc1352/Makefile.am b/examples/platforms/cc1352/Makefile.am new file mode 100644 index 000000000..7214dd1cc --- /dev/null +++ b/examples/platforms/cc1352/Makefile.am @@ -0,0 +1,86 @@ +# +# Copyright (c) 2018, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, 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 $(abs_top_nlbuild_autotools_dir)/automake/pre.am + +lib_LIBRARIES = libopenthread-cc1352.a + +# Do not enable -pedantic-errors for cc13xx driverlib +override CFLAGS := $(filter-out -pedantic-errors,$(CFLAGS)) +override CXXFLAGS := $(filter-out -pedantic-errors,$(CXXFLAGS)) + +libopenthread_cc1352_a_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/core \ + -I$(top_srcdir)/examples/platforms \ + -I$(top_srcdir)/examples/platforms/cc1352 \ + -I$(top_srcdir)/third_party/ti/devices/cc13x2_cc26x2 \ + -I$(top_srcdir)/third_party/mbedtls/repo/include \ + $(MBEDTLS_CPPFLAGS) \ + $(NULL) + +PLATFORM_SOURCES = \ + alarm.c \ + diag.c \ + flash.c \ + logging.c \ + misc.c \ + platform.c \ + radio.c \ + random.c \ + uart.c \ + crypto/aes_alt.c \ + cc1352_ccfg.c \ + cc1352_startup.c \ + cxx_helpers.c \ + $(NULL) + +libopenthread_cc1352_a_SOURCES = \ + $(PLATFORM_SOURCES) \ + $(NULL) + +libopenthread_cc1352_a_DEPENDENCIES = \ + $(top_srcdir)/third_party/ti/devices/cc13x2_cc26x2/driverlib/bin/gcc/driverlib.a \ + $(NULL) + +noinst_HEADERS = \ + platform-cc1352.h \ + $(NULL) + +PRETTY_FILES = \ + $(PLATFORM_SOURCES) \ + $(noinst_HEADERS) \ + $(NULL) + +Dash = - +libopenthread_cc1352_a_LIBADD = \ + $(shell find $(top_builddir)/examples/platforms/utils $(Dash)type f $(Dash)name "*.o") + +include $(abs_top_nlbuild_autotools_dir)/automake/post.am + diff --git a/examples/platforms/cc1352/Makefile.platform.am b/examples/platforms/cc1352/Makefile.platform.am new file mode 100644 index 000000000..9f29e0cb2 --- /dev/null +++ b/examples/platforms/cc1352/Makefile.platform.am @@ -0,0 +1,44 @@ +# +# Copyright (c) 2018, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. +# + +# +# cc1352 platform-specific Makefile +# + +CPPFLAGS_COMMON += \ + -I$(top_srcdir)/third_party/ti/devices/cc13x2_cc26x2 \ + $(NULL) + +LDADD_COMMON += \ + $(top_builddir)/examples/platforms/cc1352/libopenthread-cc1352.a \ + $(top_srcdir)/third_party/ti/devices/cc13x2_cc26x2/driverlib/bin/gcc/driverlib.a \ + $(NULL) + +LDFLAGS_COMMON += \ + -T $(top_srcdir)/third_party/ti/devices/cc13x2_cc26x2/linker_files/cc26x2r1f.lds \ + $(NULL) diff --git a/examples/platforms/cc1352/README.md b/examples/platforms/cc1352/README.md new file mode 100644 index 000000000..152aabba9 --- /dev/null +++ b/examples/platforms/cc1352/README.md @@ -0,0 +1,120 @@ +# OpenThread on CC1352 Example + +This directory contains example platform drivers for the [Texas Instruments +CC1352R1][cc1352r1]. + +The example platform drivers are intended to present the minimal code necessary +to support OpenThread. As a result, the example platform drivers do not +necessarily highlight the platform's full capabilities. Consult the [SimpleLink +CC26X2R1 SDK][cc26x2r1-sdk] for more development option. The platform drivers +were built for the [CC1352R1 LAUNCHXL][cc1352r1-launchxl], usage on other +boards with a cc1352r1 may require changes to the peripheral drivers. + +[cc1352r1-launchxl]: http://www.ti.com/tool/launchxl-cc26x2r1 +[cc26x2r1-sdk]: http://www.ti.com/tool/simplelink-cc26x2-sdk + +[cc1352r1]: http://www.ti.com/tool/launchxl-cc26x2r1 + +## Toolchain + +Building the examples for the cc1352 requires [GNU AutoConf][gnu-autoconf], +[GNU AutoMake][gnu-automake], [Python][python], and the [ARM gcc +toolchain][arm-toolchain]. + +With the exception of the arm toolchain, most of these tools are installed by +default on modern Posix systems. It is recommended to setup a Linux virtual +machine for building on a Windows host system. For help setting up VirtualBox +with Ubuntu, consult this [community help wiki +article][ubuntu-wiki-virtualbox]. + +[gnu-autoconf]: https://www.gnu.org/software/autoconf +[gnu-automake]: https://www.gnu.org/software/automake +[python]: https://www.python.org +[arm-toolchain]: https://launchpad.net/gcc-arm-embedded +[cygwin]: https://www.cygwin.com +[mingw]: http://www.mingw.org +[ubuntu-wiki-virtualbox]: https://help.ubuntu.com/community/VirtualBox + +In a Bash terminal, follow these instructions to install the GNU toolchain and +other dependencies. + +```bash +$ cd +$ ./script/bootstrap +``` + +## Building + +In a Bash terminal, follow these instructions to build the cc1352 examples. + +```bash +$ cd +$ ./bootstrap +$ make -f examples/Makefile-cc1352 +``` + +## Flash Binaries + +If the build completed successfully, the `elf` files may be found in +`/output/cc1352/bin`. + +Flash the images with [Uniflash][uniflash]. Make sure to deselect the binary +check-box, Uniflash assumes a file without an extension is a binary file. + +[uniflash]: http://www.ti.com/tool/uniflash + +## Interact + +### CLI example + +1. With a terminal client (PuTTY, minicom, etc.) open the com port associated + with the cc1352 UART. The serial port settings are: + * 115200 baud + * 8 data bits + * no parity bit + * 1 stop bit +2. Type `help` for a list of commands. +3. Follow the instructions in the [CLI README][cli-readme] for instructions on + setting up a network. + +[cli-readme]: ../../../src/cli/README.md + +```bash +> help +help +channel +childtimeout +contextreusedelay +extaddr +extpanid +ipaddr +keysequence +leaderweight +masterkey +mode +netdataregister +networkidtimeout +networkname +panid +ping +prefix +releaserouterid +rloc16 +route +routerupgradethreshold +scan +start +state +stop +whitelist +``` + +### NCP example + +Refer to the documentation in the [wpantund][wpantund] project for build +instructions and usage information. + +[wpantund]: https://github.com/openthread/wpantund diff --git a/examples/platforms/cc1352/alarm.c b/examples/platforms/cc1352/alarm.c new file mode 100644 index 000000000..bf4826f80 --- /dev/null +++ b/examples/platforms/cc1352/alarm.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for the alarm. + * + */ + +#include + +#include +#include +#include + +#include + +#include +#include + +#include "platform-cc1352.h" + +/* NOTE: we could use systick, but that would sacrifice atleast a few ops + * every ms, and not run when the processor is sleeping. + */ + +static uint32_t sTime0 = 0; +static uint32_t sAlarmTime = 0; +static bool sIsRunning = false; + +/** + * Function documented in platform-cc1352.h + */ +void cc1352AlarmInit(void) +{ + /* + * NOTE: this will not enable the individual rtc alarm channels + */ + AONRTCEnable(); + sIsRunning = true; +} + +/** + * Function documented in platform/alarm-milli.h + */ +uint32_t otPlatAlarmMilliGetNow(void) +{ + /* + * This is current value of RTC as it appears in the register. + * With seconds as the upper 32 bits and fractions of a second as the + * lower 32 bits <32.32>. + */ + uint64_t rtcVal = AONRTCCurrent64BitValueGet(); + return ((rtcVal * 1000) >> 32); +} + +/** + * Function documented in platform/alarm-milli.h + */ +void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) +{ + (void)aInstance; + sTime0 = aT0; + sAlarmTime = aDt; + sIsRunning = true; +} + +/** + * Function documented in platform/alarm-milli.h + */ +void otPlatAlarmMilliStop(otInstance *aInstance) +{ + (void)aInstance; + sIsRunning = false; +} + +/** + * Function documented in platform-cc1352.h + */ +void cc1352AlarmProcess(otInstance *aInstance) +{ + uint32_t offsetTime; + + if (sIsRunning) + { + /* unsinged subtraction will result in the absolute offset */ + offsetTime = otPlatAlarmMilliGetNow() - sTime0; + + if (sAlarmTime <= offsetTime) + { + sIsRunning = false; +#if OPENTHREAD_ENABLE_DIAG + + if (otPlatDiagModeGet()) + { + otPlatDiagAlarmFired(aInstance); + } + else +#endif /* OPENTHREAD_ENABLE_DIAG */ + { + otPlatAlarmMilliFired(aInstance); + } + } + } +} diff --git a/examples/platforms/cc1352/cc1352_ccfg.c b/examples/platforms/cc1352/cc1352_ccfg.c new file mode 100644 index 000000000..234f19bc0 --- /dev/null +++ b/examples/platforms/cc1352/cc1352_ccfg.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +/* + * Configure the Customer Configuration Area. + */ + +// clang-format off + +// enable bootloader backdoor +#define SET_CCFG_BL_CONFIG_BOOTLOADER_ENABLE 0xC5 // Enable ROM boot loader + +#define SET_CCFG_BL_CONFIG_BL_LEVEL 0x0 // Active low to open boot loader backdoor + +#define SET_CCFG_BL_CONFIG_BL_PIN_NUMBER 0x0F // DIO15 (BTN-1 button) on CC1352 LaunchPad Board for boot loader backdoor + +#define SET_CCFG_BL_CONFIG_BL_ENABLE 0xC5 // Enabled boot loader backdoor + +/* + * Include the default ccfg struct and configuration code. + */ +#include + +// clang-format on diff --git a/examples/platforms/cc1352/cc1352_radio.h b/examples/platforms/cc1352/cc1352_radio.h new file mode 100644 index 000000000..1ffd8eee4 --- /dev/null +++ b/examples/platforms/cc1352/cc1352_radio.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +#ifndef CC1352_RADIO_H_ +#define CC1352_RADIO_H_ + +#include + +enum +{ + IEEE802154_FRAME_TYPE_MASK = 0x7, ///< (IEEE 802.15.4-2006) PSDU.FCF.frameType + IEEE802154_FRAME_TYPE_ACK = 0x2, ///< (IEEE 802.15.4-2006) frame type: ACK + IEEE802154_ACK_REQUEST = (1<<5), ///< (IEEE 802.15.4-2006) PSDU.FCF.bAR + IEEE802154_DSN_OFFSET = 2, ///< (IEEE 802.15.4-2006) PSDU.sequenceNumber + IEEE802154_MAC_MIN_BE = 1, ///< (IEEE 802.15.4-2006) macMinBE + IEEE802154_MAC_MAX_BE = 5, ///< (IEEE 802.15.4-2006) macMaxBE + IEEE802154_MAC_MAX_CSMA_BACKOFFS = 4, ///< (IEEE 802.15.4-2006) macMaxCSMABackoffs + IEEE802154_MAC_MAX_FRAMES_RETRIES = 3, ///< (IEEE 802.15.4-2006) macMaxFrameRetries + IEEE802154_A_UINT_BACKOFF_PERIOD = 20, ///< (IEEE 802.15.4-2006 7.4.1) MAC constants + IEEE802154_A_TURNAROUND_TIME = 12, ///< (IEEE 802.15.4-2006 6.4.1) PHY constants + IEEE802154_PHY_SHR_DURATION = 10, + ///< (IEEE 802.15.4-2006 6.4.2) PHY PIB attribute, specifically the O-QPSK PHY + IEEE802154_PHY_SYMBOLS_PER_OCTET = 2, + ///< (IEEE 802.15.4-2006 6.4.2) PHY PIB attribute, specifically the O-QPSK PHY + IEEE802154_MAC_ACK_WAIT_DURATION = (IEEE802154_A_UINT_BACKOFF_PERIOD + + IEEE802154_A_TURNAROUND_TIME + + IEEE802154_PHY_SHR_DURATION + + ( 6 * IEEE802154_PHY_SYMBOLS_PER_OCTET)), + ///< (IEEE 802.15.4-2006 7.4.2) macAckWaitDuration PIB attribute + IEEE802154_SYMBOLS_PER_SEC = 62500 ///< (IEEE 802.15.4-2006 6.5.3.2) O-QPSK symbol rate +}; + +enum +{ + CC1352_RAT_TICKS_PER_SEC = 4000000, ///< 4MHz clock + CC1352_INVALID_RSSI = 127, + CC1352_UNKNOWN_EUI64 = 0xFF, + ///< If the EUI64 read from the ccfg is all ones then the customer did not set the address +}; + +/** + * TX Power dBm lookup table - values from SmartRF Studio + */ +typedef struct output_config +{ + int dbm; + uint16_t value; +} output_config_t; + +/** + * * TX Power dBm lookup table from SmartRF Studio 7 2.10.0#94 + */ +static const output_config_t rgOutputPower[] = +{ + { 5, 0x941E}, + { 4, 0x6c16}, + { 3, 0x5411}, + { 2, 0x440d}, + { 1, 0x385c}, + { 0, 0x3459}, + { -3, 0x2851}, + { -5, 0x224e}, + { -6, 0x204d}, + { -9, 0x0a8d}, + { -10, 0x168c}, + { -12, 0x108a}, + { -15, 0xc88c}, + { -18, 0x06c9}, + { -21, 0x06c7}, +}; + +#define OUTPUT_CONFIG_COUNT (sizeof(rgOutputPower) / sizeof(rgOutputPower[0])) + +/* Max and Min Output Power in dBm */ +#define OUTPUT_POWER_MIN (rgOutputPower[OUTPUT_CONFIG_COUNT - 1].dbm) +#define OUTPUT_POWER_MAX (rgOutputPower[0].dbm) +#define OUTPUT_POWER_UNKNOWN 0xFFFF + +/** + * return value used when searching the source match array + */ +#define CC1352_SRC_MATCH_NONE 0xFF + +/** + * number of extended addresses used for source matching + */ +#define CC1352_EXTADD_SRC_MATCH_NUM 10 + +/** + * structure for source matching extended addresses + */ +typedef struct __attribute__((aligned(4))) ext_src_match_data +{ + uint32_t srcMatchEn[((CC1352_EXTADD_SRC_MATCH_NUM + 31) / 32)]; + uint32_t srcPendEn[((CC1352_EXTADD_SRC_MATCH_NUM + 31) / 32)]; + uint64_t extAddrEnt[CC1352_EXTADD_SRC_MATCH_NUM]; +} ext_src_match_data_t; + +/** + * number of short addresses used for source matching + */ +#define CC1352_SHORTADD_SRC_MATCH_NUM 10 + +/** + * structure for source matching short addresses + */ +typedef struct __attribute__((aligned(4))) short_src_match_data +{ + uint32_t srcMatchEn[((CC1352_SHORTADD_SRC_MATCH_NUM + 31) / 32)]; + uint32_t srcPendEn[((CC1352_SHORTADD_SRC_MATCH_NUM + 31) / 32)]; + rfc_shortAddrEntry_t extAddrEnt[CC1352_SHORTADD_SRC_MATCH_NUM]; +} short_src_match_data_t; + +/** + * size of length field in receive struct + * + * defined in Table 23-10 of the cc26xx TRM + */ +#define DATA_ENTRY_LENSZ_BYTE 1 + +/** + * address type for @ref rfCoreModifySourceMatchEntry() + */ +typedef enum cc1352_address +{ + SHORT_ADDRESS = 1, + EXT_ADDRESS = 0, +} cc1352_address_t; + +/** + * This enum represents the state of a radio. + * Initially, a radio is in the Disabled state. + * + * The following are valid radio state transitions for the cc1352: + * + * (Radio ON) + * +----------+ Enable() +-------+ Receive() +---------+ Transmit() +----------+ + * | |----------->| |------------->| |--------------->| | + * | Disabled | | Sleep | | Receive | | Transmit | + * | |<-----------| |<-------------| |<---------------| | + * +----------+ Disable() | | Sleep() | | AckFrame RX or +----------+ + * | | (Radio OFF) +---------+ sTxCmdChainDone == true + * | | + * | | EnergyScan() +--------+ + * | |------------->| | + * | | | EdScan | + * | |<-------------| | + * | | signal ED | | + * +-------+ scan done +--------+ + * + * These states slightly differ from the states in \ref include/platform/radio.h. + * The additional states the phy can be in are due to the asynchronous nature + * of the CM0 radio core. + * + * | state | description | + * |------------------|----------------------------------------------------| + * | Disabled | The rfcore powerdomain is off and the RFCPE is off | + * | Sleep | The RFCORE PD is on, and the RFCPE is in IEEE mode | + * | Receive | The RFCPE is running a CMD_IEEE_RX | + * | Transmit | The RFCPE is running a transmit command string | + * | TransmitComplete | The transmit command string has completed | + * | EdScan | The RFCPE is running a CMD_IEEE_ED_SCAN | + * + * \note The RAT start and Radio Setup commands may be moved to the Receive() + * and EnergyScan() transitions in the future. + */ +typedef enum cc1352_PhyState +{ + cc1352_stateDisabled = 0, + cc1352_stateSleep, + cc1352_stateReceive, + cc1352_stateEdScan, + cc1352_stateTransmit, +} cc1352_PhyState_t; + +#endif /* CC1352_RADIO_H_ */ diff --git a/examples/platforms/cc1352/cc1352_startup.c b/examples/platforms/cc1352/cc1352_startup.c new file mode 100644 index 000000000..b6134d4c6 --- /dev/null +++ b/examples/platforms/cc1352/cc1352_startup.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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 the standard startup files for the specified toolchain + * startup code is in 'third_party/ti' + */ +#if defined(__GNUC__) +#include +#elif defined(__TI_ARM__) +#include +#else +#error "Unknown compiler" +#endif diff --git a/examples/platforms/cc1352/crypto/aes_alt.c b/examples/platforms/cc1352/crypto/aes_alt.c new file mode 100644 index 000000000..5bfa44de0 --- /dev/null +++ b/examples/platforms/cc1352/crypto/aes_alt.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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 "aes_alt.h" +#include "mbedtls/aes.h" + +#ifdef MBEDTLS_AES_ALT + +#include +#include +#include +#include + +#define CC1352_AES_KEY_UNUSED (-1) +#define CC1352_AES_CTX_MAGIC (0x7E) + +/** + * bitmap of which key stores are currently used + */ +static uint8_t sUsedKeys = 0; + +/** + * number of active contexts, used for power on/off of the crypto core + */ +static unsigned int sRefNum = 0; + +/* + * Documented in aes_alt.h + */ +void mbedtls_aes_init(mbedtls_aes_context *ctx) +{ + if (sRefNum++ == 0) + { + /* enable the crypto core */ + /* The TRNG should already be running before we ever ask the AES core + * to do anything, if there is any scenario that the TRNG powers off + * the peripheral power domain use this code to repower it + + PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH); + while (PRCMPowerDomainStatus(PRCM_DOMAIN_PERIPH) != PRCM_DOMAIN_POWER_ON); + */ + PRCMPeripheralRunEnable(PRCM_PERIPH_CRYPTO); + PRCMPeripheralSleepEnable(PRCM_PERIPH_CRYPTO); + PRCMPeripheralDeepSleepEnable(PRCM_PERIPH_CRYPTO); + PRCMLoadSet(); + + while (!PRCMLoadGet()) + ; + } + + ctx->magic = CC1352_AES_CTX_MAGIC; + ctx->key_idx = CC1352_AES_KEY_UNUSED; +} + +/* + * Documented in aes_alt.h + */ +void mbedtls_aes_free(mbedtls_aes_context *ctx) +{ + otEXPECT(ctx->magic == CC1352_AES_CTX_MAGIC); + + if (ctx->key_idx != CC1352_AES_KEY_UNUSED) + { + sUsedKeys &= ~(1 << ctx->key_idx); + } + + if (--sRefNum == 0) + { + /* disable the crypto core */ + /* The TRNG core needs the peripheral power domain powered on to + * function. if there is a situation where the power domain must be + * powered off, use this code to do so. + + PRCMPowerDomainOff(PRCM_DOMAIN_PERIPH); + while (PRCMPowerDomainStatus(PRCM_DOMAIN_PERIPH) != PRCM_DOMAIN_POWER_OFF); + */ + PRCMPeripheralRunDisable(PRCM_PERIPH_CRYPTO); + PRCMPeripheralSleepDisable(PRCM_PERIPH_CRYPTO); + PRCMPeripheralDeepSleepDisable(PRCM_PERIPH_CRYPTO); + PRCMLoadSet(); + + while (!PRCMLoadGet()) + ; + } + + memset((void *)ctx, 0x00, sizeof(ctx)); + +exit: + return; +} + +/* + * Documented in aes_alt.h + */ +int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) +{ + unsigned char key_idx; + int retval = 0; + + otEXPECT_ACTION(ctx->magic == CC1352_AES_CTX_MAGIC, retval = -1); + + if (ctx->key_idx != CC1352_AES_KEY_UNUSED) + { + sUsedKeys &= ~(1 << ctx->key_idx); + } + + /* our hardware only supports 128 bit keys */ + otEXPECT_ACTION(keybits == 128u, retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH); + + for (key_idx = 0; ((sUsedKeys >> key_idx) & 0x01) != 0 && key_idx < 8; key_idx++) + ; + + /* we have no more room for this key */ + otEXPECT_ACTION(key_idx < 8, retval = -2); + + otEXPECT_ACTION(CRYPTOAesLoadKey((uint32_t *)key, key_idx) == AES_SUCCESS, + retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH); + + sUsedKeys |= (1 << key_idx); + ctx->key_idx = key_idx; +exit: + return retval; +} + +/* + * Documented in aes_alt.h + */ +int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) +{ + unsigned char key_idx; + int retval = 0; + + otEXPECT_ACTION(ctx->magic == CC1352_AES_CTX_MAGIC, retval = -1); + + if (ctx->key_idx != CC1352_AES_KEY_UNUSED) + { + sUsedKeys &= ~(1 << ctx->key_idx); + } + + /* our hardware only supports 128 bit keys */ + otEXPECT_ACTION(keybits == 128u, retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH); + + for (key_idx = 0; ((sUsedKeys >> key_idx) & 0x01) != 0 && key_idx < 8; key_idx++) + ; + + /* we have no more room for this key */ + otEXPECT_ACTION(key_idx < 8, retval = -2); + + otEXPECT_ACTION(CRYPTOAesLoadKey((uint32_t *)key, key_idx) == AES_SUCCESS, + retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH); + + sUsedKeys |= (1 << key_idx); + ctx->key_idx = key_idx; +exit: + return retval; +} + +/* + * Documented in aes_alt.h + */ +int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) +{ + int retval = -1; + + retval = CRYPTOAesEcb((uint32_t *)input, (uint32_t *)output, ctx->key_idx, mode == MBEDTLS_AES_ENCRYPT, false); + otEXPECT(retval == AES_SUCCESS); + + while ((retval = CRYPTOAesEcbStatus()) == AES_DMA_BSY) + ; + + CRYPTOAesEcbFinish(); + +exit: + return retval; +} + +#endif /* MBEDTLS_AES_ALT */ diff --git a/examples/platforms/cc1352/crypto/aes_alt.h b/examples/platforms/cc1352/crypto/aes_alt.h new file mode 100644 index 000000000..4a14859a1 --- /dev/null +++ b/examples/platforms/cc1352/crypto/aes_alt.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +#ifndef MBEDTLS_AES_ALT_H +#define MBEDTLS_AES_ALT_H + +#ifndef MBEDTLS_CONFIG_FILE +#include "cc1352-mbedtls-config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#ifdef MBEDTLS_AES_ALT + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint8_t magic; + signed char key_idx; +} mbedtls_aes_context; + +/** + * @brief Initialize AES context + * + * @param [in,out] ctx AES context to be initialized + */ +void mbedtls_aes_init(mbedtls_aes_context *ctx); + +/** + * @brief Clear AES context + * + * @param [in,out] ctx AES context to be cleared + */ +void mbedtls_aes_free(mbedtls_aes_context *ctx); + +/** + * @brief AES key schedule (encryption) + * + * @param [in,out] ctx AES context to be used + * @param [in] key Encryption key + * @param [in] keybits Must be 128 + * + * @retval 0 If successful + * @retval MBEDTLS_ERR_AES_INVALID_KEY_LENGTH If keybits was not 128 + */ +int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits); + +/** + * @brief AES key schedule (decryption) + * + * @param [in,out] ctx AES context to be used + * @param [in] key Decryption key + * @param [in] keybits Must be 128 + * + * @retval 0 If successful + * @retval MBEDTLS_ERR_AES_INVALID_KEY_LENGTH If keybits was not 128 + */ +int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits); + +/** + * \brief AES-ECB block encryption/decryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * @return The return value of @ref CRYPTOAesEcb. + * @retval 0 If successful + * @retval AES_KEYSTORE_READ_ERROR If the indicated keystore ram could not be read + */ +int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], + unsigned char output[16]); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_AES_ALT */ + +#endif /* MBEDTLS_AES_ALT_H */ diff --git a/examples/platforms/cc1352/crypto/cc1352-mbedtls-config.h b/examples/platforms/cc1352/crypto/cc1352-mbedtls-config.h new file mode 100644 index 000000000..5ebb3535e --- /dev/null +++ b/examples/platforms/cc1352/crypto/cc1352-mbedtls-config.h @@ -0,0 +1,2543 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#include +#include + +#include + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/mbedtls/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Comment if your system does not support time functions + */ +//#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h and time(), gmtime() and the clock is correct. + * The time needs to be correct (not necesarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + */ +//#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto or hash module (e.g. + * platform specific assembly optimized implementations). Keep in mind that + * the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base function + * declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + */ +#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_XTEA_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * Note: if you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + */ +#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +//#define MBEDTLS_CIPHER_PADDING_PKCS7 +//#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +//#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +//#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +//#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +//#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 + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +//#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +//#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +//#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +//#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +//#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +//#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +//#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SSL_AEAD_RANDOM_IV + * + * Generate a random IV rather than using the record sequence number as a + * nonce for ciphersuites using and AEAD algorithm (GCM or CCM). + * + * Using the sequence number is generally recommended. + * + * Uncomment this macro to always use random IVs with AEAD ciphersuites. + */ +//#define MBEDTLS_SSL_AEAD_RANDOM_IV + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +//#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +//#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +//#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +//#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +//#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Disable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + */ +//#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +//#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +//#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +//#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +//#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintainance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +//#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +//#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +//#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * \warning Depending on your PKI use, enabling this can be a security risk! + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +//#define MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +//#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +//#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be a applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/mbedtls_x509write_csr.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +//#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +//#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +//#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +//#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ +//#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +//#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +//#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +//#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +//#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/mbedtls_md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/mbedtls_md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/mbedtls_md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/mbedtls_md5.c + * Caller: library/mbedtls_md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ +//#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net.c + * + * This module provides networking routines. + */ +//#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * library/x509write_crt.c + * library/mbedtls_x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +//#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/mbedtls_x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +//#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +//#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +//#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +//#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/mbedtls_ripemd160.c + * Caller: library/mbedtls_md.c + * + */ +//#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +//#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/mbedtls_sha1.c + * Caller: library/mbedtls_md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +//#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/mbedtls_sha256.c + * Caller: library/entropy.c + * library/mbedtls_md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/mbedtls_sha512.c + * Caller: library/entropy.c + * library/mbedtls_md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +//#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +//#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +//#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +//#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/mbedtls_x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +//#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/mbedtls_x509_crl.c + * Caller: library/mbedtls_x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +//#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/mbedtls_x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +//#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +//#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +//#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +//#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +#define MBEDTLS_MPI_WINDOW_SIZE 1 /**< Maximum windows size used. */ +#define MBEDTLS_MPI_MAX_SIZE 32 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +#define MBEDTLS_ECP_MAX_BITS 256 /**< Maximum bit size of groups */ +#define MBEDTLS_ECP_WINDOW_SIZE 2 /**< Maximum window size used */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +#define MBEDTLS_ENTROPY_MAX_SOURCES 1 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO uint32_t /**< Default time macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ +#define MBEDTLS_SSL_MAX_CONTENT_LEN 768 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ + +/* \} name SECTION: Module configuration options */ + +#if defined(TARGET_LIKE_MBED) +#include "mbedtls/target_config.h" +#endif + +/* + * Allow user to override any previous default. + * + * Use two macro names for that, as: + * - with yotta the prefix YOTTA_CFG_ is forced + * - without yotta is looks weird to have a YOTTA prefix. + */ +#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE) +#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE +#elif defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/examples/platforms/cc1352/cxx_helpers.c b/examples/platforms/cc1352/cxx_helpers.c new file mode 100644 index 000000000..5e2d21dd7 --- /dev/null +++ b/examples/platforms/cc1352/cxx_helpers.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +/* + * Helper functions for running c++ without the standard library + */ + +__extension__ typedef int __guard __attribute__((mode(__DI__))); + +int __cxa_guard_acquire(__guard *g) +{ + return !*(char *)(g); +} + +void __cxa_guard_release(__guard *g) +{ + *(char *)g = 1; +} + +void __cxa_guard_abort(__guard *g) +{ + (void)g; +} + +void __cxa_pure_virtual(void) +{ + while (1) + ; +} diff --git a/examples/platforms/cc1352/diag.c b/examples/platforms/cc1352/diag.c new file mode 100644 index 000000000..8658d8eee --- /dev/null +++ b/examples/platforms/cc1352/diag.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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 +#include +#include + +#include +#include +#include +#include + +#include "platform-cc1352.h" + +#if OPENTHREAD_ENABLE_DIAG + +/** + * Diagnostics mode variables. + * + */ +static bool sDiagMode = false; + +void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) +{ + (void)aInstance; + + // Add more platform specific diagnostics features here. + if (argc > 1) + { + snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]); + } +} + +void otPlatDiagModeSet(bool aMode) +{ + sDiagMode = aMode; +} + +bool otPlatDiagModeGet() +{ + return sDiagMode; +} + +void otPlatDiagChannelSet(uint8_t aChannel) +{ + (void)aChannel; +} + +void otPlatDiagTxPowerSet(int8_t aTxPower) +{ + (void)aTxPower; +} + +void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError) +{ + (void)aInstance; + (void)aFrame; + (void)aError; +} + +void otPlatDiagAlarmCallback(otInstance *aInstance) +{ + (void)aInstance; +} + +#endif // OPENTHREAD_ENABLE_DIAG diff --git a/examples/platforms/cc1352/flash.c b/examples/platforms/cc1352/flash.c new file mode 100644 index 000000000..2a4a01307 --- /dev/null +++ b/examples/platforms/cc1352/flash.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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 +#include +#include +#include + +#include +#include +#include + +#include + +#include "platform-cc1352.h" + +/* + * The settings configuration base address *MUST* be defined in the core config + * file. The base address *MUST* be aligned on an 8K page boundary or the flash + * program calls will fail. + */ +#ifndef SETTINGS_CONFIG_BASE_ADDRESS +#error "SETTINGS_CONFIG_BASE_ADDRESS not defined in the OpenThread Core Config" +#endif /* SETTINGS_CONFIG_BASE_ADDRESS */ + +/* + * The settings configuration page size *MUST* be defined in the core config + * file. The page size *MUST* be 8K or the flash program calls will fail. + */ +#if (SETTINGS_CONFIG_PAGE_SIZE != 0x2000) +#error "SETTINGS_CONFIG_PAGE_SIZE must be defined in OpenThread Core Config" +#endif + +/* + * The settings configuration page number _SHOULD_ be defined in the core + * config file. + */ +#ifndef SETTINGS_CONFIG_PAGE_NUM +#warn "SETTINGS_CONFIG_PAGE_NUM not defined in the OpenThread Core Config" +#endif /* SETTINGS_CONFIG_PAGE_NUM */ + +enum +{ + MIN_VDD_FLASH = 0x18, /* 1.50 volts (0.50=128/256 -> 128=0x80) */ + MAX_WRITE_INCREMENT = 8, /* maximum number of bytes to write at a time to + * avoid interrupt latency while in ROM + */ +}; + +/** + * Check if the Battery Monitor measurements and calculations are enabled. + * + * @return If the Battery Monitor is enabled. + * @retval true The Battery Monitor is on. + * @retval false The Battery Monitor is off. + */ +static bool isBatMonOn(void) +{ + uint32_t batMonCtl = HWREG(AON_BATMON_BASE + AON_BATMON_O_CTL); + return ((batMonCtl & AON_BATMON_CTL_CALC_EN_M) == AON_BATMON_CTL_CALC_EN && + (batMonCtl & AON_BATMON_CTL_MEAS_EN_M) == AON_BATMON_CTL_MEAS_EN); +} + +/** + * Check if the supply voltage is high enough to support flash programming. + * + * @return If the Voltage is too low to support flash programming. + * @retval false The supply voltage is too low. + * @retval true The supply voltage is sufficient. + */ +static bool checkVoltage(void) +{ + bool batMonWasOff = !isBatMonOn(); + bool ret = false; + + if (batMonWasOff) + { + AONBatMonEnable(); + } + + if (AONBatMonBatteryVoltageGet() >= MIN_VDD_FLASH) + { + ret = true; + } + + if (batMonWasOff) + { + AONBatMonDisable(); + } + + return ret; +} + +/** + * Disable Flash data caching and instruction pre-fetching. + * + * It is necessary to disable the caching and VIMS to ensure the cache has + * valid data while the program is executing. + * + * @return The VIMS state before being disabled. + */ +static uint32_t disableFlashCache(void) +{ + uint32_t mode = VIMSModeGet(VIMS_BASE); + + VIMSLineBufDisable(VIMS_BASE); + + if (mode != VIMS_MODE_DISABLED) + { + VIMSModeSet(VIMS_BASE, VIMS_MODE_DISABLED); + + while (VIMSModeGet(VIMS_BASE) != VIMS_MODE_DISABLED) + ; + } + + return mode; +} + +/** + * Restore the Flash data caching and instruction pre-fetching. + * + * @param [in] mode The VIMS mode returned by @ref disableFlashCache. + */ +static void restoreFlashCache(uint32_t mode) +{ + if (mode != VIMS_MODE_DISABLED) + { + VIMSModeSet(VIMS_BASE, mode); + } + + VIMSLineBufEnable(VIMS_BASE); +} + +/** + * Translate the errors from the Flash programming FSM to OpenThread error + * codes. + * + * @param [in] error Return from the Flash programming function. + * + * @return The corresponding OpenThread @ref otError value. + */ +static otError fsmErrorToOtError(uint32_t error) +{ + otError ret = OT_ERROR_GENERIC; + + switch (error) + { + case FAPI_STATUS_SUCCESS: + ret = OT_ERROR_NONE; + break; + + case FAPI_STATUS_INCORRECT_DATABUFFER_LENGTH: + ret = OT_ERROR_INVALID_ARGS; + break; + + case FAPI_STATUS_FSM_ERROR: + ret = OT_ERROR_FAILED; + break; + + default: + break; + } + + return ret; +} + +/** + * Function documented in platforms/utils/flash.h + */ +otError utilsFlashInit(void) +{ + return OT_ERROR_NONE; +} + +/** + * Function documented in platforms/utils/flash.h + */ +uint32_t utilsFlashGetSize(void) +{ + return FlashSizeGet(); +} + +/** + * Function documented in platforms/utils/flash.h + */ +otError utilsFlashErasePage(uint32_t aAddress) +{ + uint32_t mode; + uint32_t fsmRet; + otError ret; + + otEXPECT_ACTION(checkVoltage(), ret = OT_ERROR_FAILED); + + mode = disableFlashCache(); + + fsmRet = FlashSectorErase(aAddress); + + restoreFlashCache(mode); + + ret = fsmErrorToOtError(fsmRet); + +exit: + return ret; +} + +/** + * Function documented in platforms/utils/flash.h + */ +otError utilsFlashStatusWait(uint32_t aTimeout) +{ + uint32_t start = otPlatAlarmMilliGetNow(); + otError ret = OT_ERROR_BUSY; + + while ((otPlatAlarmMilliGetNow() - start) < aTimeout) + { + if (FlashCheckFsmForReady() == FAPI_STATUS_FSM_READY) + { + ret = OT_ERROR_NONE; + break; + } + } + + return ret; +} + +/** + * Function documented in platforms/utils/flash.h + */ +uint32_t utilsFlashWrite(uint32_t aAddress, uint8_t *aData, uint32_t aSize) +{ + uint32_t mode; + uint32_t written = 0; + + otEXPECT(checkVoltage()); + + mode = disableFlashCache(); + + while (written < aSize) + { + uint32_t toWrite = aSize - written; + uint8_t *data = aData + written; + uint32_t address = aAddress + written; + uint32_t fsmRet; + bool interruptsWereDisabled; + + if (toWrite > MAX_WRITE_INCREMENT) + { + toWrite = MAX_WRITE_INCREMENT; + } + + /* The CPU may not execute code from flash while a program is + * happening. We disable interrupts to ensure one does not preempt the + * ROM fsm. + */ + interruptsWereDisabled = IntMasterDisable(); + + fsmRet = FlashProgram(data, address, toWrite); + + if (!interruptsWereDisabled) + { + IntMasterEnable(); + } + + if (fsmRet != FAPI_STATUS_SUCCESS) + { + break; + } + + written += toWrite; + } + + restoreFlashCache(mode); + +exit: + return written; +} + +/** + * Function documented in platforms/utils/flash.h + */ +uint32_t utilsFlashRead(uint32_t aAddress, uint8_t *aData, uint32_t aSize) +{ + memcpy(aData, (void *)aAddress, (size_t)aSize); + + return aSize; +} diff --git a/examples/platforms/cc1352/logging.c b/examples/platforms/cc1352/logging.c new file mode 100644 index 000000000..190a4bfa1 --- /dev/null +++ b/examples/platforms/cc1352/logging.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +/** + * @file logging.c + * Platform abstraction for the logging + * + */ +#include +#include +#include + +#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED) || \ + (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL) +OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) +{ + (void)aLogLevel; + (void)aLogRegion; + (void)aFormat; +} +#endif diff --git a/examples/platforms/cc1352/misc.c b/examples/platforms/cc1352/misc.c new file mode 100644 index 000000000..a95a42236 --- /dev/null +++ b/examples/platforms/cc1352/misc.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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 +#include +#include + +/* + * NOTE: if the system is flashed with Flash Programmer 2 or Uniflash, this + * reset will not work the first time. Both programs use the cJTAG module, + * which sets the halt in boot flag. The device must be manually reset the + * first time after being programmed through the JTAG interface. + */ + +/** + * Function documented in platform/misc.h + */ +void otPlatReset(otInstance *aInstance) +{ + (void)aInstance; + SysCtrlSystemReset(); +} + +/** + * Function documented in platform/misc.h + */ +otPlatResetReason otPlatGetResetReason(otInstance *aInstance) +{ + (void)aInstance; + otPlatResetReason ret; + + switch (SysCtrlResetSourceGet()) + { + case RSTSRC_PWR_ON: + ret = OT_PLAT_RESET_REASON_POWER_ON; + break; + + case RSTSRC_PIN_RESET: + ret = OT_PLAT_RESET_REASON_EXTERNAL; + break; + + case RSTSRC_VDDS_LOSS: + case RSTSRC_VDDR_LOSS: + case RSTSRC_CLK_LOSS: + ret = OT_PLAT_RESET_REASON_CRASH; + break; + + case RSTSRC_WARMRESET: + case RSTSRC_SYSRESET: + case RSTSRC_WAKEUP_FROM_SHUTDOWN: + ret = OT_PLAT_RESET_REASON_SOFTWARE; + break; + + default: + ret = OT_PLAT_RESET_REASON_UNKNOWN; + break; + } + + return ret; +} + +void otPlatWakeHost(void) +{ + // TODO: implement an operation to wake the host from sleep state. +} diff --git a/examples/platforms/cc1352/openthread-core-cc1352-config.h b/examples/platforms/cc1352/openthread-core-cc1352-config.h new file mode 100644 index 000000000..13c87dece --- /dev/null +++ b/examples/platforms/cc1352/openthread-core-cc1352-config.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +#ifndef OPENTHREAD_CORE_CC1352_CONFIG_H_ +#define OPENTHREAD_CORE_CC1352_CONFIG_H_ + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_INFO + * + * The platform-specific string to insert into the OpenThread version string. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_INFO "CC1352" + +/** + * @def SETTINGS_CONFIG_BASE_ADDRESS + * + * The base address of the pages to be used for non-volatile-settings storage. + */ +#define SETTINGS_CONFIG_BASE_ADDRESS (0x52000) + +/** + * @def SETTINGS_CONFIG_PAGE_SIZE + * + * The size in bytes of a page for the cc26x2 platform. + * + * @note *MUST BE* 8K. + */ +#define SETTINGS_CONFIG_PAGE_SIZE (0x2000) + +/** + * @def SETTINGS_CONFIG_PAGE_NUM + * + * The number of flash pages to use for non-volatile settings storage. + */ +#define SETTINGS_CONFIG_PAGE_NUM (2) + +#endif /* OPENTHREAD_CORE_CC1352_CONFIG_H_ */ + diff --git a/examples/platforms/cc1352/platform-cc1352.h b/examples/platforms/cc1352/platform-cc1352.h new file mode 100644 index 000000000..927712526 --- /dev/null +++ b/examples/platforms/cc1352/platform-cc1352.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +#ifndef PLATFORM_H_ +#define PLATFORM_H_ + +#include +#include +#include +#include "openthread/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Global OpenThread instance structure +extern otInstance *sInstance; + +/** + * Initialize the debug uart + */ +void cc1352DebugUartInit(void); + +/** + * This method initializes the alarm service used by OpenThread. + * + */ +void cc1352AlarmInit(void); + +/** + * This method performs alarm driver processing. + * + */ +void cc1352AlarmProcess(otInstance *aInstance); + +/** + * This method initializes the radio service used by OpenThread. + * + */ +void cc1352RadioInit(void); + +/** + * This method performs radio driver processing. + * + */ +void cc1352RadioProcess(otInstance *aInstance); + +/** + * This method initializes the random number service used by OpenThread. + * + */ +void cc1352RandomInit(void); + +/** + * This method performs radio driver processing. + * + */ +void cc1352UartProcess(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // PLATFORM_H_ diff --git a/examples/platforms/cc1352/platform.c b/examples/platforms/cc1352/platform.c new file mode 100644 index 000000000..77881e4eb --- /dev/null +++ b/examples/platforms/cc1352/platform.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +/** + * @file + * @brief + * This file includes the platform-specific initializers. + */ + +#include + +#include "platform-cc1352.h" +#include +#include + +#include "inc/hw_ccfg.h" +#include "inc/hw_ccfg_simple_struct.h" +#include "inc/hw_types.h" + +extern const ccfg_t __ccfg; + +const char *dummy_ccfg_ref = ((const char *)(&(__ccfg))); + +/** + * Function documented in platform-cc1352.h + */ +void PlatformInit(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + + while (dummy_ccfg_ref == NULL) + { + /* + * This provides a code reference to the customer configuration area of + * the flash, otherwise the data is skipped by the linker and not put + * into the final flash image. + */ + } + +#if OPENTHREAD_CONFIG_ENABLE_DEBUG_UART + cc1352DebugUartInit(); +#endif + cc1352AlarmInit(); + cc1352RandomInit(); + cc1352RadioInit(); +} + +bool PlatformPseudoResetWasRequested(void) +{ + return false; +} + +/** + * Function documented in platform-cc1352.h + */ +void PlatformProcessDrivers(otInstance *aInstance) +{ + // should sleep and wait for interrupts here + + cc1352UartProcess(); + cc1352RadioProcess(aInstance); + cc1352AlarmProcess(aInstance); +} diff --git a/examples/platforms/cc1352/radio.c b/examples/platforms/cc1352/radio.c new file mode 100644 index 000000000..f7f2db0f7 --- /dev/null +++ b/examples/platforms/cc1352/radio.c @@ -0,0 +1,1970 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for radio communication. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include /* to seed the CSMA-CA funciton */ + +#include "cc1352_radio.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum +{ + CC1352_RECEIVE_SENSITIVITY = -100, // dBm +}; + +/* phy state as defined by openthread */ +static volatile cc1352_PhyState_t sState; + +/* set to max transmit power by default */ +static output_config_t const *sCurrentOutputPower = &(rgOutputPower[0]); + +/* Overrides from SmartRF Studio 7 2.10.0#94 */ +static uint32_t sIEEEOverrides[] = { + // override_ieee_802_15_4.xml + // PHY: Use MCE RAM patch, RFE ROM bank 1 + MCE_RFE_OVERRIDE(1, 0, 0, 0, 1, 0), + // Synth: Use 48 MHz crystal, enable extra PLL filtering + (uint32_t)0x02400403, + // Synth: Configure extra PLL filtering + (uint32_t)0x001C8473, + // Synth: Configure synth hardware + (uint32_t)0x00088433, + // Synth: Set minimum RTRIM to 3 + (uint32_t)0x00038793, + // Synth: Configure faster calibration + HW32_ARRAY_OVERRIDE(0x4004, 1), + // Synth: Configure faster calibration + (uint32_t)0x1C0C0618, + // Synth: Configure faster calibration + (uint32_t)0xC00401A1, + // Synth: Configure faster calibration + (uint32_t)0x00010101, + // Synth: Configure faster calibration + (uint32_t)0xC0040141, + // Synth: Configure faster calibration + (uint32_t)0x00214AD3, + // Synth: Decrease synth programming time-out (0x0298 RAT ticks = 166 us) + (uint32_t)0x02980243, + // DC/DC regulator: In Tx, use DCDCCTL5[3:0]=0xC (DITHER_EN=1 and IPEAK=4). In Rx, use DCDCCTL5[3:0]=0xC + // (DITHER_EN=1 and IPEAK=4). + (uint32_t)0xFCFC08C3, + // Rx: Set LNA bias current offset to +15 to saturate trim to max (default: 0) + (uint32_t)0x000F8883, + // override_frontend_id.xml + (uint32_t)0xFFFFFFFF, +}; + +/* + * Number of retry counts left to the currently transmitting frame. + * + * Initialized when a frame is passed to be sent over the air, and decremented + * by the radio ISR every time the transmit command string fails to receive a + * corresponding ack. + */ +static volatile unsigned int sTransmitRetryCount = 0; + +/* + * Offset of the radio timer from the rtc. + * + * Used when we start and stop the RAT on enabling and disabling of the rf + * core. + */ +static uint32_t sRatOffset = 0; + +/* + * Radio command structures that run on the CM0. + */ +// clang-format off +static volatile __attribute__((aligned(4))) rfc_CMD_SYNC_START_RAT_t sStartRatCmd; +static volatile __attribute__((aligned(4))) rfc_CMD_RADIO_SETUP_t sRadioSetupCmd; + +static volatile __attribute__((aligned(4))) rfc_CMD_FS_POWERDOWN_t sFsPowerdownCmd; +static volatile __attribute__((aligned(4))) rfc_CMD_SYNC_STOP_RAT_t sStopRatCmd; + +static volatile __attribute__((aligned(4))) rfc_CMD_CLEAR_RX_t sClearReceiveQueueCmd; +static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_MOD_FILT_t sModifyReceiveFilterCmd; +static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_MOD_SRC_MATCH_t sModifyReceiveSrcMatchCmd; + +static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_ED_SCAN_t sEdScanCmd; + +static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_RX_t sReceiveCmd; + +static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_CSMA_t sCsmacaBackoffCmd; +static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_TX_t sTransmitCmd; +static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_RX_ACK_t sTransmitRxAckCmd; + +static volatile __attribute__((aligned(4))) ext_src_match_data_t sSrcMatchExtData; +static volatile __attribute__((aligned(4))) short_src_match_data_t sSrcMatchShortData; +// clang-format on + +/* + * Structure containing radio statistics. + */ +static __attribute__((aligned(4))) rfc_ieeeRxOutput_t sRfStats; + +/* + * Two receive buffers entries with room for 1 max IEEE802.15.4 frame in each + * + * These will be setup in a circular buffer configuration by /ref sRxDataQueue. + */ +#define RX_BUF_SIZE 144 +static __attribute__((aligned(4))) uint8_t sRxBuf0[RX_BUF_SIZE]; +static __attribute__((aligned(4))) uint8_t sRxBuf1[RX_BUF_SIZE]; +static __attribute__((aligned(4))) uint8_t sRxBuf2[RX_BUF_SIZE]; +static __attribute__((aligned(4))) uint8_t sRxBuf3[RX_BUF_SIZE]; + +/* + * The RX Data Queue used by @ref sReceiveCmd. + */ +static __attribute__((aligned(4))) dataQueue_t sRxDataQueue = {0}; + +/* + * OpenThread data primitives + */ +static otRadioFrame sTransmitFrame; +static otError sTransmitError; + +static __attribute__((aligned(4))) uint8_t sTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE]; + +static volatile bool sTxCmdChainDone = false; + +/* + * Interrupt handlers forward declared for register functions. + */ +void RFCCPE0IntHandler(void); +void RFCCPE1IntHandler(void); + +/** + * Initialize the RX/TX buffers. + * + * Zeros out the receive and transmit buffers and sets up the data structures + * of the receive queue. + */ +static void rfCoreInitBufs(void) +{ + rfc_dataEntry_t *entry; + memset(sRxBuf0, 0x00, sizeof(sRxBuf0)); + memset(sRxBuf1, 0x00, sizeof(sRxBuf1)); + memset(sRxBuf2, 0x00, sizeof(sRxBuf2)); + memset(sRxBuf3, 0x00, sizeof(sRxBuf3)); + + entry = (rfc_dataEntry_t *)sRxBuf0; + entry->pNextEntry = sRxBuf1; + entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; + entry->length = sizeof(sRxBuf0) - sizeof(rfc_dataEntry_t); + + entry = (rfc_dataEntry_t *)sRxBuf1; + entry->pNextEntry = sRxBuf2; + entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; + entry->length = sizeof(sRxBuf1) - sizeof(rfc_dataEntry_t); + + entry = (rfc_dataEntry_t *)sRxBuf2; + entry->pNextEntry = sRxBuf3; + entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; + entry->length = sizeof(sRxBuf2) - sizeof(rfc_dataEntry_t); + + entry = (rfc_dataEntry_t *)sRxBuf3; + entry->pNextEntry = sRxBuf0; + entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; + entry->length = sizeof(sRxBuf3) - sizeof(rfc_dataEntry_t); + + sTransmitFrame.mPsdu = sTransmitPsdu; + sTransmitFrame.mLength = 0; +} + +/** + * Initialize the RX command structure. + * + * Sets the default values for the receive command structure. + */ +static void rfCoreInitReceiveParams(void) +{ + // clang-format off + static const rfc_CMD_IEEE_RX_t cReceiveCmd = + { + .commandNo = CMD_IEEE_RX, + .status = IDLE, + .pNextOp = NULL, + .startTime = 0u, + .startTrigger = + { + .triggerType = TRIG_NOW, + }, + .condition = { + .rule = COND_NEVER, + }, + .channel = OT_RADIO_CHANNEL_MIN, + .rxConfig = + { + .bAutoFlushCrc = 1, + .bAutoFlushIgn = 0, + .bIncludePhyHdr = 0, + .bIncludeCrc = 0, + .bAppendRssi = 1, + .bAppendCorrCrc = 1, + .bAppendSrcInd = 0, + .bAppendTimestamp = 0, + }, + .frameFiltOpt = + { + .frameFiltEn = 1, + .frameFiltStop = 1, + .autoAckEn = 1, + .slottedAckEn = 0, + .autoPendEn = 0, + .defaultPend = 0, + .bPendDataReqOnly = 0, + .bPanCoord = 0, + .maxFrameVersion = 3, + .bStrictLenFilter = 1, + }, + .frameTypes = + { + .bAcceptFt0Beacon = 1, + .bAcceptFt1Data = 1, + .bAcceptFt2Ack = 1, + .bAcceptFt3MacCmd = 1, + .bAcceptFt4Reserved = 1, + .bAcceptFt5Reserved = 1, + .bAcceptFt6Reserved = 1, + .bAcceptFt7Reserved = 1, + }, + .ccaOpt = + { + .ccaEnEnergy = 1, + .ccaEnCorr = 1, + .ccaEnSync = 1, + .ccaCorrOp = 1, + .ccaSyncOp = 0, + .ccaCorrThr = 3, + }, + .ccaRssiThr = -90, + .endTrigger = + { + .triggerType = TRIG_NEVER, + }, + .endTime = 0u, + }; + // clang-format on + sReceiveCmd = cReceiveCmd; + + sReceiveCmd.pRxQ = &sRxDataQueue; + sReceiveCmd.pOutput = &sRfStats; + + sReceiveCmd.numShortEntries = CC1352_SHORTADD_SRC_MATCH_NUM; + sReceiveCmd.pShortEntryList = (void *)&sSrcMatchShortData; + + sReceiveCmd.numExtEntries = CC1352_EXTADD_SRC_MATCH_NUM; + sReceiveCmd.pExtEntryList = (uint32_t *)&sSrcMatchExtData; +} + +/** + * Sends the direct abort command to the radio core. + * + * @return The value from the command status register. + * @retval CMDSTA_Done The command completed correctly. + */ +static uint_fast8_t rfCoreExecuteAbortCmd(void) +{ + return (RFCDoorbellSendTo(CMDR_DIR_CMD(CMD_ABORT)) & 0xFF); +} + +/** + * Sends the direct ping command to the radio core. + * + * Check that the Radio core is alive and able to respond to commands. + * + * @return The value from the command status register. + * @retval CMDSTA_Done The command completed correctly. + */ +static uint_fast8_t rfCoreExecutePingCmd(void) +{ + return (RFCDoorbellSendTo(CMDR_DIR_CMD(CMD_PING)) & 0xFF); +} + +/** + * Sends the immediate clear rx queue command to the radio core. + * + * Uses the radio core to mark all of the entries in the receive queue as + * pending. This is used instead of clearing the entries manually to avoid race + * conditions between the main processor and the radio core. + * + * @param [in] aQueue A pointer to the receive queue to be cleared. + * + * @return The value from the command status register. + * @retval CMDSTA_Done The command completed correctly. + */ +static uint_fast8_t rfCoreClearReceiveQueue(dataQueue_t *aQueue) +{ + /* memset skipped because sClearReceiveQueueCmd has only 2 members and padding */ + sClearReceiveQueueCmd.commandNo = CMD_CLEAR_RX; + sClearReceiveQueueCmd.pQueue = aQueue; + + return (RFCDoorbellSendTo((uint32_t)&sClearReceiveQueueCmd) & 0xFF); +} + +/** + * Enable/disable frame filtering. + * + * Uses the radio core to alter the current running RX command filtering + * options. This ensures there is no access fault between the CM3 and CM0 for + * the RX command. + * + * This function leaves the type of frames to be filtered the same as the + * receive command. + * + * @note An IEEE RX command *must* be running while this command executes. + * + * @param [in] aEnable TRUE: enable frame filtering, + * FALSE: disable frame filtering. + * + * @return The value from the command status register. + * @retval CMDSTA_Done The command completed correctly. + */ +static uint_fast8_t rfCoreModifyRxFrameFilter(bool aEnable) +{ + /* memset skipped because sModifyReceiveFilterCmd has only 3 members */ + sModifyReceiveFilterCmd.commandNo = CMD_IEEE_MOD_FILT; + /* copy current frame filtering and frame types from running RX command */ + memcpy((void *)&sModifyReceiveFilterCmd.newFrameFiltOpt, (void *)&sReceiveCmd.frameFiltOpt, + sizeof(sModifyReceiveFilterCmd.newFrameFiltOpt)); + memcpy((void *)&sModifyReceiveFilterCmd.newFrameTypes, (void *)&sReceiveCmd.frameTypes, + sizeof(sModifyReceiveFilterCmd.newFrameTypes)); + + sModifyReceiveFilterCmd.newFrameFiltOpt.frameFiltEn = aEnable ? 1 : 0; + + return (RFCDoorbellSendTo((uint32_t)&sModifyReceiveFilterCmd) & 0xFF); +} + +/** + * Enable/disable autoPend feature. + * + * Uses the radio core to alter the current running RX command filtering + * options. This ensures there is no access fault between the CM3 and CM0 for + * the RX command. + * + * This function leaves the type of frames to be filtered the same as the + * receive command. + * + * @note An IEEE RX command *must* be running while this command executes. + * + * @param [in] aEnable TRUE: enable autoPend, + * FALSE: disable autoPend. + * + * @return The value from the command status register. + * @retval CMDSTA_Done The command completed correctly. + */ +static uint_fast8_t rfCoreModifyRxAutoPend(bool aEnable) +{ + /* memset skipped because sModifyReceiveFilterCmd has only 3 members */ + sModifyReceiveFilterCmd.commandNo = CMD_IEEE_MOD_FILT; + /* copy current frame filtering and frame types from running RX command */ + memcpy((void *)&sModifyReceiveFilterCmd.newFrameFiltOpt, (void *)&sReceiveCmd.frameFiltOpt, + sizeof(sModifyReceiveFilterCmd.newFrameFiltOpt)); + memcpy((void *)&sModifyReceiveFilterCmd.newFrameTypes, (void *)&sReceiveCmd.frameTypes, + sizeof(sModifyReceiveFilterCmd.newFrameTypes)); + + sModifyReceiveFilterCmd.newFrameFiltOpt.autoPendEn = aEnable ? 1 : 0; + + return (RFCDoorbellSendTo((uint32_t)&sModifyReceiveFilterCmd) & 0xFF); +} + +/** + * Sends the immediate modify source matching command to the radio core. + * + * Uses the radio core to alter the current source matching parameters used by + * the running RX command. This ensures there is no access fault between the + * CM3 and CM0, and ensures that the RX command has cohesive view of the data. + * The CM3 may make alterations to the source matching entries if the entry is + * marked as disabled. + * + * @note An IEEE RX command *must* be running while this command executes. + * + * @param [in] aEntryNo The index of the entry to alter. + * @param [in] aType TRUE: the entry is a short address, + * FALSE: the entry is an extended address. + * @param [in] aEnable Whether the given entry is to be enabled or disabled. + * + * @return The value from the command status register. + * @retval CMDSTA_Done The command completed correctly. + */ +static uint_fast8_t rfCoreModifySourceMatchEntry(uint8_t aEntryNo, cc1352_address_t aType, bool aEnable) +{ + /* memset kept to save 60 bytes of text space, gcc can't optimize the + * following bitfield operation if it doesn't know the fields are zero + * already. + */ + memset((void *)&sModifyReceiveSrcMatchCmd, 0, sizeof(sModifyReceiveSrcMatchCmd)); + + sModifyReceiveSrcMatchCmd.commandNo = CMD_IEEE_MOD_SRC_MATCH; + + /* we only use source matching for pending data bit, so enabling and + * pending are the same to us. + */ + if (aEnable) + { + sModifyReceiveSrcMatchCmd.options.bEnable = 1; + sModifyReceiveSrcMatchCmd.options.srcPend = 1; + } + else + { + sModifyReceiveSrcMatchCmd.options.bEnable = 0; + sModifyReceiveSrcMatchCmd.options.srcPend = 0; + } + + sModifyReceiveSrcMatchCmd.options.entryType = aType; + sModifyReceiveSrcMatchCmd.entryNo = aEntryNo; + + return (RFCDoorbellSendTo((uint32_t)&sModifyReceiveSrcMatchCmd) & 0xFF); +} + +/** + * Walks the short address source match list to find an address. + * + * @param [in] aAddress The short address to search for. + * + * @return The index where the address was found. + * @retval CC1352_SRC_MATCH_NONE The address was not found. + */ +static uint8_t rfCoreFindShortSrcMatchIdx(const uint16_t aAddress) +{ + uint8_t i; + uint8_t ret = CC1352_SRC_MATCH_NONE; + + for (i = 0; i < CC1352_SHORTADD_SRC_MATCH_NUM; i++) + { + if (sSrcMatchShortData.extAddrEnt[i].shortAddr == aAddress) + { + ret = i; + break; + } + } + + return ret; +} + +/** + * Walks the short address source match list to find an empty slot. + * + * @return The index of an unused address slot. + * @retval CC1352_SRC_MATCH_NONE No unused slots available. + */ +static uint8_t rfCoreFindEmptyShortSrcMatchIdx(void) +{ + uint8_t i; + uint8_t ret = CC1352_SRC_MATCH_NONE; + + for (i = 0; i < CC1352_SHORTADD_SRC_MATCH_NUM; i++) + { + if ((sSrcMatchShortData.srcMatchEn[i / 32] & (1 << (i % 32))) == 0u) + { + ret = i; + break; + } + } + + return ret; +} + +/** + * Walks the extended address source match list to find an address. + * + * @param [in] aAddress The extended address to search for. + * + * @return The index where the address was found. + * @retval CC1352_SRC_MATCH_NONE The address was not found. + */ +static uint8_t rfCoreFindExtSrcMatchIdx(const uint64_t *aAddress) +{ + uint8_t i; + uint8_t ret = CC1352_SRC_MATCH_NONE; + + for (i = 0; i < CC1352_EXTADD_SRC_MATCH_NUM; i++) + { + if (sSrcMatchExtData.extAddrEnt[i] == *aAddress) + { + ret = i; + break; + } + } + + return ret; +} + +/** + * Walks the extended address source match list to find an empty slot. + * + * @return The index of an unused address slot. + * @retval CC1352_SRC_MATCH_NONE No unused slots available. + */ +static uint8_t rfCoreFindEmptyExtSrcMatchIdx(void) +{ + uint8_t i; + uint8_t ret = CC1352_SRC_MATCH_NONE; + + for (i = 0; i < CC1352_EXTADD_SRC_MATCH_NUM; i++) + { + if ((sSrcMatchExtData.srcMatchEn[i / 32] & (1 << (i % 32))) != 0u) + { + ret = i; + break; + } + } + + return ret; +} + +/** + * Sends the tx command to the radio core. + * + * Sends the packet to the radio core to be sent asynchronously. + * + * @note @ref aPsdu *must* be 4 byte aligned and not include the FCS. + * + * @param [in] aPsdu A pointer to the data to be sent. + * @param [in] aLen The length in bytes of data pointed to by PSDU. + * + * @return The value from the command status register. + * @retval CMDSTA_Done The command completed correctly. + */ +static uint_fast8_t rfCoreSendTransmitCmd(uint8_t *aPsdu, uint8_t aLen) +{ + // clang-format off + static const rfc_CMD_IEEE_CSMA_t cCsmacaBackoffCmd = + { + .commandNo = CMD_IEEE_CSMA, + .status = IDLE, + .startTrigger = + { + .triggerType = TRIG_NOW, + }, + .condition = { + .rule = COND_ALWAYS, + }, + .macMaxBE = IEEE802154_MAC_MAX_BE, + .macMaxCSMABackoffs = IEEE802154_MAC_MAX_CSMA_BACKOFFS, + .csmaConfig = + { + .initCW = 1, + .bSlotted = 0, + .rxOffMode = 0, + }, + .NB = 0, + .BE = IEEE802154_MAC_MIN_BE, + .remainingPeriods = 0, + .endTrigger = + { + .triggerType = TRIG_NEVER, + }, + .endTime = 0x00000000, + }; + static const rfc_CMD_IEEE_TX_t cTransmitCmd = + { + .commandNo = CMD_IEEE_TX, + .status = IDLE, + .startTrigger = + { + .triggerType = TRIG_NOW, + }, + .condition = { + .rule = COND_NEVER, + }, + .pNextOp = NULL, + }; + static const rfc_CMD_IEEE_RX_ACK_t cTransmitRxAckCmd = + { + .commandNo = CMD_IEEE_RX_ACK, + .status = IDLE, + .startTrigger = + { + .triggerType = TRIG_NOW, + }, + .endTrigger = + { + .triggerType = TRIG_REL_START, + .pastTrig = 1, + }, + .condition = { + .rule = COND_NEVER, + }, + .pNextOp = NULL, + /* number of RAT ticks to wait before claiming we haven't received an ack */ + .endTime = ((IEEE802154_MAC_ACK_WAIT_DURATION * CC1352_RAT_TICKS_PER_SEC) / IEEE802154_SYMBOLS_PER_SEC), + }; + // clang-format on + + /* reset retry count */ + sTransmitRetryCount = 0; + + sCsmacaBackoffCmd = cCsmacaBackoffCmd; + /* initialize the random state with a true random seed for the radio core's + * psudo rng */ + sCsmacaBackoffCmd.randomState = otPlatRandomGet(); + sCsmacaBackoffCmd.pNextOp = (rfc_radioOp_t *)&sTransmitCmd; + + sTransmitCmd = cTransmitCmd; + /* no need to look for an ack if the tx operation was stopped */ + sTransmitCmd.payloadLen = aLen; + sTransmitCmd.pPayload = aPsdu; + + if (aPsdu[0] & IEEE802154_ACK_REQUEST) + { + /* setup the receive ack command to follow the tx command */ + sTransmitCmd.condition.rule = COND_STOP_ON_FALSE; + sTransmitCmd.pNextOp = (rfc_radioOp_t *)&sTransmitRxAckCmd; + + sTransmitRxAckCmd = cTransmitRxAckCmd; + sTransmitRxAckCmd.seqNo = aPsdu[IEEE802154_DSN_OFFSET]; + } + + return (RFCDoorbellSendTo((uint32_t)&sCsmacaBackoffCmd) & 0xFF); +} + +/** + * Sends the rx command to the radio core. + * + * Sends the pre-built receive command to the radio core. This sets up the + * radio to receive packets according to the settings in the global rx command. + * + * @note This function does not alter any of the parameters of the rx command. + * It is only concerned with sending the command to the radio core. See @ref + * otPlatRadioSetPanId for an example of how the rx settings are set changed. + * + * @return The value from the command status register. + * @retval CMDSTA_Done The command completed correctly. + */ +static uint_fast8_t rfCoreSendReceiveCmd(void) +{ + sReceiveCmd.status = IDLE; + return (RFCDoorbellSendTo((uint32_t)&sReceiveCmd) & 0xFF); +} + +static uint_fast8_t rfCoreSendEdScanCmd(uint8_t aChannel, uint16_t aDurration) +{ + // clang-format off + static const rfc_CMD_IEEE_ED_SCAN_t cEdScanCmd = + { + .commandNo = CMD_IEEE_ED_SCAN, + .startTrigger = + { + .triggerType = TRIG_NOW, + }, + .condition = { + .rule = COND_NEVER, + }, + .ccaOpt = + { + .ccaEnEnergy = 1, + .ccaEnCorr = 1, + .ccaEnSync = 1, + .ccaCorrOp = 1, + .ccaSyncOp = 0, + .ccaCorrThr = 3, + }, + .ccaRssiThr = -90, + .endTrigger = + { + .triggerType = TRIG_REL_START, + .pastTrig = 1, + }, + }; + // clang-format on + sEdScanCmd = cEdScanCmd; + + sEdScanCmd.channel = aChannel; + + /* durration is in ms */ + sEdScanCmd.endTime = aDurration * (CC1352_RAT_TICKS_PER_SEC / 1000); + + return (RFCDoorbellSendTo((uint32_t)&sEdScanCmd) & 0xFF); +} + +/** + * Enables the cpe0 and cpe1 radio interrupts. + * + * Enables the @ref IRQ_LAST_COMMAND_DONE and @ref IRQ_LAST_FG_COMMAND_DONE to + * be handled by the @ref RFCCPE0IntHandler interrupt handler. + */ +static void rfCoreSetupInt(void) +{ + bool interruptsWereDisabled; + + otEXPECT(PRCMRfReady()); + + interruptsWereDisabled = IntMasterDisable(); + + /* Set all interrupt channels to CPE0 channel, error to CPE1 */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = IRQ_INTERNAL_ERROR; + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = IRQ_LAST_COMMAND_DONE | IRQ_LAST_FG_COMMAND_DONE; + + IntRegister(INT_RFC_CPE_0, RFCCPE0IntHandler); + IntRegister(INT_RFC_CPE_1, RFCCPE1IntHandler); + IntPendClear(INT_RFC_CPE_0); + IntPendClear(INT_RFC_CPE_1); + IntEnable(INT_RFC_CPE_0); + IntEnable(INT_RFC_CPE_1); + + if (!interruptsWereDisabled) + { + IntMasterEnable(); + } + +exit: + return; +} + +/** + * Disables and clears the cpe0 and cpe1 radio interrupts. + */ +static void rfCoreStopInt(void) +{ + bool interruptsWereDisabled; + + interruptsWereDisabled = IntMasterDisable(); + + /* clear and disable interrupts */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0; + + IntUnregister(INT_RFC_CPE_0); + IntUnregister(INT_RFC_CPE_1); + IntPendClear(INT_RFC_CPE_0); + IntPendClear(INT_RFC_CPE_1); + IntDisable(INT_RFC_CPE_0); + IntDisable(INT_RFC_CPE_1); + + if (!interruptsWereDisabled) + { + IntMasterEnable(); + } +} + +/** + * Turns on the radio core. + * + * Sets up the power and resources for the radio core. + * - switches the high frequency clock to the xosc crystal + * - sets the mode for the radio core to IEEE 802.15.4 + * - initializes the rx buffers and command + * - powers on the radio core power domain + * - enables the radio core power domain + * - sets up the interrupts + * - sends the ping command to the radio core to make sure it is running + * + * @return The value from the command status register. + * @retval CMDSTA_Done The command was received. + */ +static uint_fast8_t rfCorePowerOn(void) +{ + bool interruptsWereDisabled; + bool oscSourceSwitch = false; + + /* Request the HF XOSC as the source for the HF clock. Needed before we can + * use the FS. This will only request, it will _not_ perform the switch. + */ + if (OSCClockSourceGet(OSC_SRC_CLK_HF) != OSC_XOSC_HF) + { + /* Request to switch to the crystal to enable radio operation. It takes a + * while for the XTAL to be ready so instead of performing the actual + * switch, we do other stuff while the XOSC is getting ready. + */ + OSCClockSourceSet(OSC_SRC_CLK_HF, OSC_XOSC_HF); + oscSourceSwitch = true; + } + + /* Set of RF Core data queue. Circular buffer, no last entry */ + sRxDataQueue.pCurrEntry = sRxBuf0; + sRxDataQueue.pLastEntry = NULL; + + rfCoreInitBufs(); + + /* + * Trigger a switch to the XOSC, so that we can subsequently use the RF FS + * This will block until the XOSC is actually ready, but give how we + * requested it early on, this won't be too long a wait. + * This should be done before starting the RAT. + */ + if (oscSourceSwitch) + { + /* Block until the high frequency clock source is ready */ + while (!OSCHfSourceReady()) + ; + + /* Switch the HF clock source (cc26xxware executes this from ROM) */ + OSCHfSourceSwitch(); + } + + interruptsWereDisabled = IntMasterDisable(); + + /* Enable RF Core power domain */ + PRCMPowerDomainOn(PRCM_DOMAIN_RFCORE); + + while (PRCMPowerDomainStatus(PRCM_DOMAIN_RFCORE) != PRCM_DOMAIN_POWER_ON) + ; + + PRCMDomainEnable(PRCM_DOMAIN_RFCORE); + PRCMLoadSet(); + + while (!PRCMLoadGet()) + ; + + rfCoreSetupInt(); + + if (!interruptsWereDisabled) + { + IntMasterEnable(); + } + + /* Let CPE boot */ + HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = + (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M | RFC_PWR_PWMCLKEN_CPERAM_M); + + /* Send ping (to verify RFCore is ready and alive) */ + return rfCoreExecutePingCmd(); +} + +/** + * Turns off the radio core. + * + * Switches off the power and resources for the radio core. + * - disables the interrupts + * - disables the radio core power domain + * - powers off the radio core power domain + * - switches the high frequency clock to the rcosc to save power + */ +static void rfCorePowerOff(void) +{ + rfCoreStopInt(); + + PRCMDomainDisable(PRCM_DOMAIN_RFCORE); + PRCMLoadSet(); + + while (!PRCMLoadGet()) + ; + + PRCMPowerDomainOff(PRCM_DOMAIN_RFCORE); + + while (PRCMPowerDomainStatus(PRCM_DOMAIN_RFCORE) != PRCM_DOMAIN_POWER_OFF) + ; + + if (OSCClockSourceGet(OSC_SRC_CLK_HF) != OSC_RCOSC_HF) + { + /* Request to switch to the RC osc for low power mode. */ + OSCClockSourceSet(OSC_SRC_CLK_HF, OSC_RCOSC_HF); + /* Switch the HF clock source (cc26xxware executes this from ROM) */ + OSCHfSourceSwitch(); + } +} + +/** + * Sends the setup command string to the radio core. + * + * Enables the clock line from the RTC to the RF core RAT. Enables the RAT + * timer and sets up the radio in IEEE mode. + * + * @return The value from the command status register. + * @retval CMDSTA_Done The command was received. + */ +static uint_fast16_t rfCoreSendEnableCmd(void) +{ + uint8_t doorbellRet; + bool interruptsWereDisabled; + uint_fast16_t ret; + + // clang-format off + static const rfc_CMD_SYNC_START_RAT_t cStartRatCmd = + { + .commandNo = CMD_SYNC_START_RAT, + .startTrigger = + { + .triggerType = TRIG_NOW, + }, + .condition = { + .rule = COND_STOP_ON_FALSE, + }, + }; + static const rfc_CMD_RADIO_SETUP_t cRadioSetupCmd = + { + .commandNo = CMD_RADIO_SETUP, + .startTrigger = + { + .triggerType = TRIG_NOW, + }, + .condition = { + .rule = COND_NEVER, + }, + .mode = 1, // IEEE 802.15.4 mode + }; + // clang-format on + /* turn on the clock line to the radio core */ + HWREGBITW(AON_RTC_BASE + AON_RTC_O_CTL, AON_RTC_CTL_RTC_UPD_EN_BITN) = 1; + + /* initialize the rat start command */ + sStartRatCmd = cStartRatCmd; + sStartRatCmd.pNextOp = (rfc_radioOp_t *)&sRadioSetupCmd; + sStartRatCmd.rat0 = sRatOffset; + + /* initialize radio setup command */ + sRadioSetupCmd = cRadioSetupCmd; + /* initally set the radio tx power to the max */ + sRadioSetupCmd.txPower = sCurrentOutputPower->value; + sRadioSetupCmd.pRegOverride = sIEEEOverrides; + + interruptsWereDisabled = IntMasterDisable(); + + doorbellRet = (RFCDoorbellSendTo((uint32_t)&sStartRatCmd) & 0xFF); + otEXPECT_ACTION(CMDSTA_Done == doorbellRet, ret = doorbellRet); + + /* synchronously wait for the CM0 to stop executing */ + while ((HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_LAST_COMMAND_DONE) == 0x00) + ; + + ret = sRadioSetupCmd.status; + +exit: + + if (!interruptsWereDisabled) + { + IntMasterEnable(); + } + + return ret; +} + +/** + * Sends the shutdown command string to the radio core. + * + * Powers down the frequency synthesizer and stops the RAT. + * + * @note synchronously waits until the command string completes. + * + * @return The status of the RAT stop command. + * @retval DONE_OK The command string executed properly. + */ +static uint_fast16_t rfCoreSendDisableCmd(void) +{ + uint8_t doorbellRet; + bool interruptsWereDisabled; + uint_fast16_t ret; + + // clang-format off + static const rfc_CMD_FS_POWERDOWN_t cFsPowerdownCmd = + { + .commandNo = CMD_FS_POWERDOWN, + .startTrigger = + { + .triggerType = TRIG_NOW, + }, + .condition = { + .rule = COND_ALWAYS, + }, + }; + static const rfc_CMD_SYNC_STOP_RAT_t cStopRatCmd = + { + .commandNo = CMD_SYNC_STOP_RAT, + .startTrigger = + { + .triggerType = TRIG_NOW, + }, + .condition = { + .rule = COND_NEVER, + }, + }; + // clang-format on + + HWREGBITW(AON_RTC_BASE + AON_RTC_O_CTL, AON_RTC_CTL_RTC_UPD_EN_BITN) = 1; + + /* initialize the command to power down the frequency synth */ + sFsPowerdownCmd = cFsPowerdownCmd; + sFsPowerdownCmd.pNextOp = (rfc_radioOp_t *)&sStopRatCmd; + + sStopRatCmd = cStopRatCmd; + + interruptsWereDisabled = IntMasterDisable(); + + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ~IRQ_LAST_COMMAND_DONE; + + doorbellRet = (RFCDoorbellSendTo((uint32_t)&sFsPowerdownCmd) & 0xFF); + otEXPECT_ACTION(CMDSTA_Done == doorbellRet, ret = doorbellRet); + + /* synchronously wait for the CM0 to stop */ + while ((HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_LAST_COMMAND_DONE) == 0x00) + ; + + ret = sStopRatCmd.status; + + if (sStopRatCmd.status == DONE_OK) + { + sRatOffset = sStopRatCmd.rat0; + } + +exit: + + if (!interruptsWereDisabled) + { + IntMasterEnable(); + } + + return ret; +} + +/** + * Error interrupt handler. + */ +void RFCCPE1IntHandler(void) +{ + /* Clear INTERNAL_ERROR interrupt flag */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x7FFFFFFF; +} + +/** + * Command done handler. + */ +void RFCCPE0IntHandler(void) +{ + if (HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_LAST_COMMAND_DONE) + { + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ~IRQ_LAST_COMMAND_DONE; + + if (sState == cc1352_stateReceive && sReceiveCmd.status != ACTIVE && sReceiveCmd.status != IEEE_SUSPENDED) + { + /* the rx command was probably aborted to change the channel */ + sState = cc1352_stateSleep; + } + else if (sState == cc1352_stateEdScan) + { + sState = cc1352_stateSleep; + } + } + + if (HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_LAST_FG_COMMAND_DONE) + { + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ~IRQ_LAST_FG_COMMAND_DONE; + + if (sState == cc1352_stateTransmit) + { + if (sTransmitCmd.pPayload[0] & IEEE802154_ACK_REQUEST) + { + /* we are looking for an ack */ + switch (sTransmitRxAckCmd.status) + { + case IEEE_DONE_TIMEOUT: + if (sTransmitRetryCount < IEEE802154_MAC_MAX_FRAMES_RETRIES) + { + /* re-submit the tx command chain */ + sTransmitRetryCount++; + RFCDoorbellSendTo((uint32_t)&sCsmacaBackoffCmd); + } + else + { + sTransmitError = OT_ERROR_NO_ACK; + /* signal polling function we are done transmitting, we failed to send the packet */ + sTxCmdChainDone = true; + } + + break; + + case IEEE_DONE_ACK: + sTransmitError = OT_ERROR_NONE; + /* signal polling function we are done transmitting */ + sTxCmdChainDone = true; + break; + + case IEEE_DONE_ACKPEND: + sTransmitError = OT_ERROR_NONE; + /* signal polling function we are done transmitting */ + sTxCmdChainDone = true; + break; + + default: + sTransmitError = OT_ERROR_FAILED; + /* signal polling function we are done transmitting */ + sTxCmdChainDone = true; + break; + } + } + else + { + /* The TX command was either stopped or we are not looking for + * an ack */ + switch (sTransmitCmd.status) + { + case IEEE_DONE_OK: + sTransmitError = OT_ERROR_NONE; + break; + + case IEEE_DONE_TIMEOUT: + sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE; + break; + + case IEEE_ERROR_NO_SETUP: + case IEEE_ERROR_NO_FS: + case IEEE_ERROR_SYNTH_PROG: + sTransmitError = OT_ERROR_INVALID_STATE; + break; + + case IEEE_ERROR_TXUNF: + sTransmitError = OT_ERROR_NO_BUFS; + break; + + default: + sTransmitError = OT_ERROR_FAILED; + break; + } + + /* signal polling function we are done transmitting */ + sTxCmdChainDone = true; + } + } + } +} + +/** + * Function documented in platform-cc1352.h + */ +void cc1352RadioInit(void) +{ + /* Populate the RX parameters data structure with default values */ + rfCoreInitReceiveParams(); + + sState = cc1352_stateDisabled; +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioEnable(otInstance *aInstance) +{ + otError error = OT_ERROR_BUSY; + (void)aInstance; + + if (sState == cc1352_stateSleep) + { + error = OT_ERROR_NONE; + } + else if (sState == cc1352_stateDisabled) + { + otEXPECT_ACTION(rfCorePowerOn() == CMDSTA_Done, error = OT_ERROR_FAILED); + otEXPECT_ACTION(rfCoreSendEnableCmd() == DONE_OK, error = OT_ERROR_FAILED); + + /* The CC1352R1_LAUNCHXL development board has an RF switch to enable + * usage of the same antenna between the 2.4G and sub-1G RF paths. This + * is connected to IOID 30 on the LaunchPad, and a low voltage will set + * the switch to the 2.4G path. + */ + + /* Enable the peripheral domain for the GPIO module */ + PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH); + /* Enable the GPIO module in all power modes, this will not be turned off */ + PRCMPeripheralRunEnable(PRCM_PERIPH_GPIO); + PRCMPeripheralSleepEnable(PRCM_PERIPH_GPIO); + PRCMPeripheralDeepSleepEnable(PRCM_PERIPH_GPIO); + /* Ensure the PRCM module is synced with these settings */ + PRCMLoadSet(); + /* Enable output on RF switch */ + IOCPinTypeGpioOutput(IOID_30); + /* Set the RF Switch to the 2.4 GHz path */ + GPIO_writeDio(IOID_30, 0); + + sState = cc1352_stateSleep; + } + +exit: + + if (error == OT_ERROR_FAILED) + { + rfCorePowerOff(); + sState = cc1352_stateDisabled; + } + + return error; +} + +/** + * Function documented in platform/radio.h + */ +bool otPlatRadioIsEnabled(otInstance *aInstance) +{ + (void)aInstance; + return (sState != cc1352_stateDisabled); +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioDisable(otInstance *aInstance) +{ + otError error = OT_ERROR_BUSY; + (void)aInstance; + + if (sState == cc1352_stateDisabled) + { + error = OT_ERROR_NONE; + } + else if (sState == cc1352_stateSleep) + { + rfCoreSendDisableCmd(); + /* we don't want to fail if this command string doesn't work, just turn + * off the whole core + */ + rfCorePowerOff(); + sState = cc1352_stateDisabled; + error = OT_ERROR_NONE; + } + + return error; +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration) +{ + otError error = OT_ERROR_BUSY; + (void)aInstance; + + if (sState == cc1352_stateSleep) + { + sState = cc1352_stateEdScan; + otEXPECT_ACTION(rfCoreSendEdScanCmd(aScanChannel, aScanDuration) == CMDSTA_Done, error = OT_ERROR_FAILED); + error = OT_ERROR_NONE; + } + +exit: + return error; +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower) +{ + otError error = OT_ERROR_NONE; + (void)aInstance; + + otEXPECT_ACTION(aPower != NULL, error = OT_ERROR_INVALID_ARGS); + *aPower = sCurrentOutputPower->dbm; + +exit: + return error; +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower) +{ + unsigned int i; + output_config_t const *powerCfg = &(rgOutputPower[0]); + (void)aInstance; + + for (i = 1; i < OUTPUT_CONFIG_COUNT; i++) + { + if (rgOutputPower[i].dbm >= aPower) + { + powerCfg = &(rgOutputPower[i]); + } + else + { + break; + } + } + + sCurrentOutputPower = powerCfg; + + return OT_ERROR_NONE; +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) +{ + otError error = OT_ERROR_BUSY; + (void)aInstance; + + if (sState == cc1352_stateSleep) + { + sState = cc1352_stateReceive; + + /* + * initialize the receive command + * XXX: no memset here because we assume init has been called and we + * may have changed some values in the rx command + */ + sReceiveCmd.channel = aChannel; + otEXPECT_ACTION(rfCoreSendReceiveCmd() == CMDSTA_Done, error = OT_ERROR_FAILED); + error = OT_ERROR_NONE; + } + else if (sState == cc1352_stateReceive) + { + if (sReceiveCmd.status == ACTIVE && sReceiveCmd.channel == aChannel) + { + /* we are already running on the right channel */ + sState = cc1352_stateReceive; + error = OT_ERROR_NONE; + } + else + { + /* + * we have either not fallen back into our receive command or + * we are running on the wrong channel. Either way assume the + * caller correctly called us and abort all running commands. + */ + otEXPECT_ACTION(rfCoreExecuteAbortCmd() == CMDSTA_Done, error = OT_ERROR_FAILED); + + /* any frames in the queue will be for the old channel */ + otEXPECT_ACTION(rfCoreClearReceiveQueue(&sRxDataQueue) == CMDSTA_Done, error = OT_ERROR_FAILED); + + sReceiveCmd.channel = aChannel; + otEXPECT_ACTION(rfCoreSendReceiveCmd() == CMDSTA_Done, error = OT_ERROR_FAILED); + + sState = cc1352_stateReceive; + error = OT_ERROR_NONE; + } + } + +exit: + return error; +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioSleep(otInstance *aInstance) +{ + otError error = OT_ERROR_BUSY; + (void)aInstance; + + if (sState == cc1352_stateSleep) + { + error = OT_ERROR_NONE; + } + else if (sState == cc1352_stateReceive) + { + if (rfCoreExecuteAbortCmd() != CMDSTA_Done) + { + error = OT_ERROR_BUSY; + } + else + { + sState = cc1352_stateSleep; + } + } + + return error; +} + +/** + * Function documented in platform/radio.h + */ +otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) +{ + (void)aInstance; + return &sTransmitFrame; +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) +{ + otError error = OT_ERROR_BUSY; + + if (sState == cc1352_stateReceive) + { + sState = cc1352_stateTransmit; + + /* removing 2 bytes of CRC placeholder because we generate that in hardware */ + otEXPECT_ACTION(rfCoreSendTransmitCmd(aFrame->mPsdu, aFrame->mLength - 2) == CMDSTA_Done, + error = OT_ERROR_FAILED); + error = OT_ERROR_NONE; + sTransmitError = OT_ERROR_NONE; + sTxCmdChainDone = false; + otPlatRadioTxStarted(aInstance, aFrame); + } + +exit: + return error; +} + +/** + * Function documented in platform/radio.h + */ +int8_t otPlatRadioGetRssi(otInstance *aInstance) +{ + (void)aInstance; + return sRfStats.maxRssi; +} + +/** + * Function documented in platform/radio.h + */ +otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) +{ + (void)aInstance; + return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_TRANSMIT_RETRIES; +} + +/** + * Function documented in platform/radio.h + */ +void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable) +{ + (void)aInstance; + + if (sReceiveCmd.status == ACTIVE || sReceiveCmd.status == IEEE_SUSPENDED) + { + /* we have a running or backgrounded rx command */ + rfCoreModifyRxAutoPend(aEnable); + } + else + { + /* if we are promiscuous, then frame filtering should be disabled */ + sReceiveCmd.frameFiltOpt.autoPendEn = aEnable ? 1 : 0; + } +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) +{ + otError error = OT_ERROR_NONE; + (void)aInstance; + uint8_t idx = rfCoreFindShortSrcMatchIdx(aShortAddress); + + if (idx == CC1352_SRC_MATCH_NONE) + { + /* the entry does not exist already, add it */ + otEXPECT_ACTION((idx = rfCoreFindEmptyShortSrcMatchIdx()) != CC1352_SRC_MATCH_NONE, error = OT_ERROR_NO_BUFS); + sSrcMatchShortData.extAddrEnt[idx].shortAddr = aShortAddress; + sSrcMatchShortData.extAddrEnt[idx].panId = sReceiveCmd.localPanID; + } + + if (sReceiveCmd.status == ACTIVE || sReceiveCmd.status == IEEE_SUSPENDED) + { + /* we have a running or backgrounded rx command */ + otEXPECT_ACTION(rfCoreModifySourceMatchEntry(idx, SHORT_ADDRESS, true) == CMDSTA_Done, error = OT_ERROR_FAILED); + } + else + { + /* we are not running, so we must update the values ourselves */ + sSrcMatchShortData.srcPendEn[idx / 32] |= (1 << (idx % 32)); + sSrcMatchShortData.srcMatchEn[idx / 32] |= (1 << (idx % 32)); + } + +exit: + return error; +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) +{ + otError error = OT_ERROR_NONE; + (void)aInstance; + uint8_t idx; + otEXPECT_ACTION((idx = rfCoreFindShortSrcMatchIdx(aShortAddress)) != CC1352_SRC_MATCH_NONE, + error = OT_ERROR_NO_ADDRESS); + + if (sReceiveCmd.status == ACTIVE || sReceiveCmd.status == IEEE_SUSPENDED) + { + /* we have a running or backgrounded rx command */ + otEXPECT_ACTION(rfCoreModifySourceMatchEntry(idx, SHORT_ADDRESS, false) == CMDSTA_Done, + error = OT_ERROR_FAILED); + } + else + { + /* we are not running, so we must update the values ourselves */ + sSrcMatchShortData.srcPendEn[idx / 32] &= ~(1 << (idx % 32)); + sSrcMatchShortData.srcMatchEn[idx / 32] &= ~(1 << (idx % 32)); + } + +exit: + return error; +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress) +{ + otError error = OT_ERROR_NONE; + (void)aInstance; + uint8_t idx = rfCoreFindExtSrcMatchIdx((uint64_t *)aExtAddress); + + if (idx == CC1352_SRC_MATCH_NONE) + { + /* the entry does not exist already, add it */ + otEXPECT_ACTION((idx = rfCoreFindEmptyExtSrcMatchIdx()) != CC1352_SRC_MATCH_NONE, error = OT_ERROR_NO_BUFS); + sSrcMatchExtData.extAddrEnt[idx] = *((uint64_t *)aExtAddress); + } + + if (sReceiveCmd.status == ACTIVE || sReceiveCmd.status == IEEE_SUSPENDED) + { + /* we have a running or backgrounded rx command */ + otEXPECT_ACTION(rfCoreModifySourceMatchEntry(idx, EXT_ADDRESS, true) == CMDSTA_Done, error = OT_ERROR_FAILED); + } + else + { + /* we are not running, so we must update the values ourselves */ + sSrcMatchExtData.srcPendEn[idx / 32] |= (1 << (idx % 32)); + sSrcMatchExtData.srcMatchEn[idx / 32] |= (1 << (idx % 32)); + } + +exit: + return error; +} + +/** + * Function documented in platform/radio.h + */ +otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress) +{ + otError error = OT_ERROR_NONE; + (void)aInstance; + uint8_t idx; + otEXPECT_ACTION((idx = rfCoreFindExtSrcMatchIdx((uint64_t *)aExtAddress)) != CC1352_SRC_MATCH_NONE, + error = OT_ERROR_NO_ADDRESS); + + if (sReceiveCmd.status == ACTIVE || sReceiveCmd.status == IEEE_SUSPENDED) + { + /* we have a running or backgrounded rx command */ + otEXPECT_ACTION(rfCoreModifySourceMatchEntry(idx, EXT_ADDRESS, false) == CMDSTA_Done, error = OT_ERROR_FAILED); + } + else + { + /* we are not running, so we must update the values ourselves */ + sSrcMatchExtData.srcPendEn[idx] = 0u; + sSrcMatchExtData.srcMatchEn[idx] = 0u; + sSrcMatchExtData.srcPendEn[idx / 32] &= ~(1 << (idx % 32)); + sSrcMatchExtData.srcMatchEn[idx / 32] &= ~(1 << (idx % 32)); + } + +exit: + return error; +} + +/** + * Function documented in platform/radio.h + */ +void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance) +{ + (void)aInstance; + + if (sReceiveCmd.status == ACTIVE || sReceiveCmd.status == IEEE_SUSPENDED) + { + unsigned int i; + + for (i = 0; i < CC1352_SHORTADD_SRC_MATCH_NUM; i++) + { + /* we have a running or backgrounded rx command */ + otEXPECT(rfCoreModifySourceMatchEntry(i, SHORT_ADDRESS, false) == CMDSTA_Done); + } + } + else + { + /* we are not running, so we can erase them ourselves */ + memset((void *)&sSrcMatchShortData, 0, sizeof(sSrcMatchShortData)); + } + +exit: + return; +} + +/** + * Function documented in platform/radio.h + */ +void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance) +{ + (void)aInstance; + + if (sReceiveCmd.status == ACTIVE || sReceiveCmd.status == IEEE_SUSPENDED) + { + unsigned int i; + + for (i = 0; i < CC1352_EXTADD_SRC_MATCH_NUM; i++) + { + /* we have a running or backgrounded rx command */ + otEXPECT(rfCoreModifySourceMatchEntry(i, EXT_ADDRESS, false) == CMDSTA_Done); + } + } + else + { + /* we are not running, so we can erase them ourselves */ + memset((void *)&sSrcMatchExtData, 0, sizeof(sSrcMatchExtData)); + } + +exit: + return; +} + +/** + * Function documented in platform/radio.h + */ +bool otPlatRadioGetPromiscuous(otInstance *aInstance) +{ + (void)aInstance; + /* we are promiscuous if we are not filtering */ + return sReceiveCmd.frameFiltOpt.frameFiltEn == 0; +} + +/** + * Function documented in platform/radio.h + */ +void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable) +{ + (void)aInstance; + + if (sReceiveCmd.status == ACTIVE || sReceiveCmd.status == IEEE_SUSPENDED) + { + /* we have a running or backgrounded rx command */ + /* if we are promiscuous, then frame filtering should be disabled */ + rfCoreModifyRxFrameFilter(!aEnable); + /* XXX should we dump any queued messages ? */ + } + else + { + /* if we are promiscuous, then frame filtering should be disabled */ + sReceiveCmd.frameFiltOpt.frameFiltEn = aEnable ? 0 : 1; + } +} + +/** + * Function documented in platform/radio.h + */ +void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64) +{ + uint8_t * eui64; + unsigned int i; + (void)aInstance; + + /* + * The IEEE MAC address can be stored two places. We check the Customer + * Configuration was not set before defaulting to the Factory + * Configuration. + */ + eui64 = (uint8_t *)(CCFG_BASE + CCFG_O_IEEE_MAC_0); + + for (i = 0; i < OT_EXT_ADDRESS_SIZE; i++) + { + if (eui64[i] != CC1352_UNKNOWN_EUI64) + { + break; + } + } + + if (i >= OT_EXT_ADDRESS_SIZE) + { + /* The ccfg address was all 0xFF, switch to the fcfg */ + eui64 = (uint8_t *)(FCFG1_BASE + FCFG1_O_MAC_15_4_0); + } + + /* + * The IEEE MAC address is stored in network byte order. The caller seems + * to want the address stored in little endian format, which is backwards + * of the conventions setup by @ref otPlatRadioSetExtendedAddress. + * otPlatRadioSetExtendedAddress assumes that the address being passed to + * it is in network byte order, so the caller of + * otPlatRadioSetExtendedAddress must swap the endianness before calling. + * + * It may be easier to have the caller of this function store the IEEE + * address in network byte order. + */ + for (i = 0; i < OT_EXT_ADDRESS_SIZE; i++) + { + aIeeeEui64[i] = eui64[(OT_EXT_ADDRESS_SIZE - 1) - i]; + } +} + +/** + * Function documented in platform/radio.h + * + * @note it is entirely possible for this function to fail, but there is no + * valid way to return that error since the function prototype was changed. + */ +void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanid) +{ + (void)aInstance; + + /* XXX: if the pan id is the broadcast pan id (0xFFFF) the auto ack will + * not work. This is due to the design of the CM0 and follows IEEE 802.15.4 + */ + if (sState == cc1352_stateReceive) + { + otEXPECT(rfCoreExecuteAbortCmd() == CMDSTA_Done); + sReceiveCmd.localPanID = aPanid; + otEXPECT(rfCoreClearReceiveQueue(&sRxDataQueue) == CMDSTA_Done); + otEXPECT(rfCoreSendReceiveCmd() == CMDSTA_Done); + /* the interrupt from abort changed our state to sleep */ + sState = cc1352_stateReceive; + } + else if (sState != cc1352_stateTransmit) + { + sReceiveCmd.localPanID = aPanid; + } + +exit: + return; +} + +/** + * Function documented in platform/radio.h + * + * @note it is entirely possible for this function to fail, but there is no + * valid way to return that error since the function prototype was changed. + */ +void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aAddress) +{ + (void)aInstance; + + /* XXX: assuming little endian format */ + if (sState == cc1352_stateReceive) + { + otEXPECT(rfCoreExecuteAbortCmd() == CMDSTA_Done); + sReceiveCmd.localExtAddr = *((uint64_t *)(aAddress)); + otEXPECT(rfCoreClearReceiveQueue(&sRxDataQueue) == CMDSTA_Done); + otEXPECT(rfCoreSendReceiveCmd() == CMDSTA_Done); + /* the interrupt from abort changed our state to sleep */ + sState = cc1352_stateReceive; + } + else if (sState != cc1352_stateTransmit) + { + sReceiveCmd.localExtAddr = *((uint64_t *)(aAddress)); + } + +exit: + return; +} + +/** + * Function documented in platform/radio.h + * + * @note it is entirely possible for this function to fail, but there is no + * valid way to return that error since the function prototype was changed. + */ +void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress) +{ + (void)aInstance; + + if (sState == cc1352_stateReceive) + { + otEXPECT(rfCoreExecuteAbortCmd() == CMDSTA_Done); + sReceiveCmd.localShortAddr = aAddress; + otEXPECT(rfCoreClearReceiveQueue(&sRxDataQueue) == CMDSTA_Done); + otEXPECT(rfCoreSendReceiveCmd() == CMDSTA_Done); + /* the interrupt from abort changed our state to sleep */ + sState = cc1352_stateReceive; + } + else if (sState != cc1352_stateTransmit) + { + sReceiveCmd.localShortAddr = aAddress; + } + +exit: + return; +} + +static void cc1352RadioProcessTransmitDone(otInstance * aInstance, + otRadioFrame *aTransmitFrame, + otRadioFrame *aAckFrame, + otError aTransmitError) +{ +#if OPENTHREAD_ENABLE_DIAG + + if (otPlatDiagModeGet()) + { + otPlatDiagRadioTransmitDone(aInstance, aTransmitFrame, aTransmitError); + } + else +#endif /* OPENTHREAD_ENABLE_DIAG */ + { + otPlatRadioTxDone(aInstance, aTransmitFrame, aAckFrame, aTransmitError); + } +} + +static void cc1352RadioProcessReceiveDone(otInstance *aInstance, otRadioFrame *aReceiveFrame, otError aReceiveError) +{ +#if OPENTHREAD_ENABLE_DIAG + + if (otPlatDiagModeGet()) + { + otPlatDiagRadioReceiveDone(aInstance, aReceiveFrame, aReceiveError); + } + else +#endif /* OPENTHREAD_ENABLE_DIAG */ + { + otPlatRadioReceiveDone(aInstance, aReceiveFrame, aReceiveError); + } +} + +static void cc1352RadioProcessReceiveQueue(otInstance *aInstance) +{ + rfc_ieeeRxCorrCrc_t * crcCorr; + rfc_dataEntryGeneral_t *curEntry, *startEntry; + uint8_t rssi; + + startEntry = (rfc_dataEntryGeneral_t *)sRxDataQueue.pCurrEntry; + curEntry = startEntry; + + /* loop through receive queue */ + do + { + uint8_t *payload = &(curEntry->data); + + if (curEntry->status == DATA_ENTRY_FINISHED) + { + uint8_t len; + otError receiveError; + otRadioFrame receiveFrame; + + /* get the information appended to the end of the frame. + * This array access looks like it is a fencepost error, but the + * first byte is the number of bytes that follow. + */ + len = payload[0]; + crcCorr = (rfc_ieeeRxCorrCrc_t *)&payload[len]; + rssi = payload[len - 1]; + + if (crcCorr->status.bCrcErr == 0 && (len - 2) < OT_RADIO_FRAME_MAX_SIZE) + { +#if OPENTHREAD_ENABLE_RAW_LINK_API + // TODO: Propagate CM0 timestamp + receiveFrame.mInfo.mRxInfo.mMsec = otPlatAlarmMilliGetNow(); + receiveFrame.mInfo.mRxInfo.mUsec = 0; // Don't support microsecond timer for now. +#endif + + receiveFrame.mLength = len; + receiveFrame.mPsdu = &(payload[1]); + receiveFrame.mChannel = sReceiveCmd.channel; + receiveFrame.mInfo.mRxInfo.mRssi = rssi; + receiveFrame.mInfo.mRxInfo.mLqi = crcCorr->status.corr; + + receiveError = OT_ERROR_NONE; + } + else + { + receiveError = OT_ERROR_FCS; + } + + if ((receiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK) + { + if (receiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET]) + { + sState = cc1352_stateReceive; + cc1352RadioProcessTransmitDone(aInstance, &sTransmitFrame, &receiveFrame, receiveError); + } + } + else + { + cc1352RadioProcessReceiveDone(aInstance, &receiveFrame, receiveError); + } + + curEntry->status = DATA_ENTRY_PENDING; + break; + } + else if (curEntry->status == DATA_ENTRY_UNFINISHED) + { + curEntry->status = DATA_ENTRY_PENDING; + } + + curEntry = (rfc_dataEntryGeneral_t *)(curEntry->pNextEntry); + } while (curEntry != startEntry); +} + +/** + * Function documented in platform-cc1352.h + */ +void cc1352RadioProcess(otInstance *aInstance) +{ + if (sState == cc1352_stateEdScan) + { + if (sEdScanCmd.status == IEEE_DONE_OK) + { + otPlatRadioEnergyScanDone(aInstance, sEdScanCmd.maxRssi); + } + else if (sEdScanCmd.status == ACTIVE) + { + otPlatRadioEnergyScanDone(aInstance, CC1352_INVALID_RSSI); + } + } + + if (sState == cc1352_stateReceive || sState == cc1352_stateTransmit) + { + cc1352RadioProcessReceiveQueue(aInstance); + } + + if (sTxCmdChainDone) + { + if (sState == cc1352_stateTransmit) + { + /* we are not looking for an ACK packet, or failed */ + sState = cc1352_stateReceive; + cc1352RadioProcessTransmitDone(aInstance, &sTransmitFrame, NULL, sTransmitError); + } + + sTransmitError = OT_ERROR_NONE; + sTxCmdChainDone = false; + } +} + +int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) +{ + (void)aInstance; + return CC1352_RECEIVE_SENSITIVITY; +} diff --git a/examples/platforms/cc1352/random.c b/examples/platforms/cc1352/random.c new file mode 100644 index 000000000..1e20a0449 --- /dev/null +++ b/examples/platforms/cc1352/random.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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 + +#include +#include +#include + +#include +#include + +enum +{ + CC1352_TRNG_MIN_SAMPLES_PER_CYCLE = (1 << 6), + CC1352_TRNG_MAX_SAMPLES_PER_CYCLE = (1 << 24), + CC1352_TRNG_CLOCKS_PER_SAMPLE = 0, +}; + +/** + * \note if more than 32 bits of entropy are needed, the TRNG core produces + * 64 bits of random data, we just ignore the upper 32 bytes + */ + +/** + * Function documented in platform-cc1352.h + */ +void cc1352RandomInit(void) +{ + PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH); + + while (PRCMPowerDomainStatus(PRCM_DOMAIN_PERIPH) != PRCM_DOMAIN_POWER_ON) + ; + + PRCMPeripheralRunEnable(PRCM_PERIPH_TRNG); + PRCMPeripheralSleepEnable(PRCM_DOMAIN_PERIPH); + PRCMPeripheralDeepSleepEnable(PRCM_DOMAIN_PERIPH); + PRCMLoadSet(); + TRNGConfigure(CC1352_TRNG_MIN_SAMPLES_PER_CYCLE, CC1352_TRNG_MAX_SAMPLES_PER_CYCLE, CC1352_TRNG_CLOCKS_PER_SAMPLE); + TRNGEnable(); +} + +/** + * Function documented in platform/random.h + */ +uint32_t otPlatRandomGet(void) +{ + while (!(TRNGStatusGet() & TRNG_NUMBER_READY)) + ; + + return TRNGNumberGet(TRNG_LOW_WORD); +} + +/** + * Fill an arbitrary area with random data. + * + * @param [out] aOutput Area to place the random data. + * @param [in] aLen Size of the area to place random data. + * @param [out] oLen How much of the output was written to. + * + * @return Indication of error. + * @retval 0 No error occurred. + */ +static int TRNGPoll(unsigned char *aOutput, size_t aLen) +{ + size_t length = 0; + union + { + uint32_t u32[2]; + uint8_t u8[8]; + } buffer; + + while (length < aLen) + { + if (length % 8 == 0) + { + /* we've run to the end of the buffer */ + while (!(TRNGStatusGet() & TRNG_NUMBER_READY)) + ; + + /* + * don't use TRNGNumberGet here because it will tell the TRNG to + * refill the entropy pool, instead we do it ourself. + */ + buffer.u32[0] = HWREG(TRNG_BASE + TRNG_O_OUT0); + buffer.u32[1] = HWREG(TRNG_BASE + TRNG_O_OUT1); + HWREG(TRNG_BASE + TRNG_O_IRQFLAGCLR) = 0x1; + } + + aOutput[length] = buffer.u8[length % 8]; + + length++; + } + + return 0; +} + +/** + * Function documented in platform/random.h + */ +otError otPlatRandomGetTrue(uint8_t *aOutput, uint16_t aOutputLength) +{ + otError error = OT_ERROR_NONE; + size_t length = aOutputLength; + + otEXPECT_ACTION(aOutput, error = OT_ERROR_INVALID_ARGS); + + otEXPECT_ACTION(TRNGPoll((unsigned char *)aOutput, length) == 0, error = OT_ERROR_FAILED); + +exit: + return error; +} diff --git a/examples/platforms/cc1352/uart.c b/examples/platforms/cc1352/uart.c new file mode 100644 index 000000000..f7ec0845c --- /dev/null +++ b/examples/platforms/cc1352/uart.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for UART communication. + * + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "utils/code_utils.h" + +#include + +#include +#include +#include +#include + +/** + * @note This will configure the uart for 115200 baud 8-N-1, no HW flow control + * RX pin IOID_2 TX pin IOID_3. + * + * If the DEBUG UART is enabled, IOID_0 = debug tx, IOID_1 = debug rx + */ + +enum +{ + CC1352_RECV_CIRC_BUFF_SIZE = 256, +}; + +static uint8_t const *sSendBuffer = NULL; +static uint16_t sSendLen = 0; + +static uint8_t sReceiveBuffer[CC1352_RECV_CIRC_BUFF_SIZE]; +static uint16_t sReceiveHeadIdx = 0; +static uint16_t sReceiveTailIdx = 0; + +void UART0_intHandler(void); + +static void uart_power_control(uint32_t who_base, int turnon) +{ + uint32_t value; + + if (turnon) + { + /* UART0 is in the SERIAL domain + * UART1 is in the PERIPH domain. + * See: ti/devices/cc13x2_cc26x2/driverlib/pcrm.h, line: 658 + */ + value = (who_base == UART0_BASE) ? PRCM_DOMAIN_SERIAL : PRCM_DOMAIN_PERIPH; + PRCMPowerDomainOn(value); + + while (PRCMPowerDomainStatus(value) != PRCM_DOMAIN_POWER_ON) + ; + + value = (who_base == UART0_BASE) ? PRCM_PERIPH_UART0 : PRCM_PERIPH_UART1; + PRCMPeripheralRunEnable(value); + PRCMPeripheralSleepEnable(value); + PRCMPeripheralDeepSleepEnable(value); + PRCMLoadSet(); + + while (!PRCMLoadGet()) + ; + } + else + { + if (who_base == UART0_BASE) + { + PRCMPeripheralRunDisable(PRCM_PERIPH_UART0); + PRCMPeripheralSleepDisable(PRCM_PERIPH_UART0); + PRCMPeripheralDeepSleepDisable(PRCM_PERIPH_UART0); + PRCMLoadSet(); + PRCMPowerDomainOff(PRCM_DOMAIN_SERIAL); + } + else + { + /* we never turn the debug uart off */ + } + } +} + +/** + * Function documented in platform/uart.h + */ +otError otPlatUartEnable(void) +{ + uart_power_control(UART0_BASE, true); + + IOCPinTypeUart(UART0_BASE, IOID_12, IOID_13, IOID_UNUSED, IOID_UNUSED); + UARTConfigSetExpClk(UART0_BASE, SysCtrlClockGet(), 115200, + UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE); + + /* Note: UART1 could use IRQs + * However, for reasons of debug simplicity + * we do not use IRQs for the debug uart + */ + UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT); + UARTIntRegister(UART0_BASE, UART0_intHandler); + UARTEnable(UART0_BASE); + + return OT_ERROR_NONE; +} + +/** + * Function documented in platform/uart.h + */ +otError otPlatUartDisable(void) +{ + UARTDisable(UART0_BASE); + UARTIntUnregister(UART0_BASE); + UARTIntDisable(UART0_BASE, UART_INT_RX | UART_INT_RT); + IOCPortConfigureSet(IOID_2, IOC_PORT_GPIO, IOC_STD_INPUT); + IOCPortConfigureSet(IOID_3, IOC_PORT_GPIO, IOC_STD_INPUT); + + uart_power_control(UART0_BASE, false); + + return OT_ERROR_NONE; +} + +/** + * Function documented in platform/uart.h + */ +otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) +{ + otError error = OT_ERROR_NONE; + otEXPECT_ACTION(sSendBuffer == NULL, error = OT_ERROR_BUSY); + + sSendBuffer = aBuf; + sSendLen = aBufLength; + +exit: + return error; +} + +/** + * @brief process the receive side of the buffers + */ +static void processReceive(void) +{ + while (sReceiveHeadIdx != sReceiveTailIdx) + { + uint16_t tailIdx; + + if (sReceiveHeadIdx < sReceiveTailIdx) + { + tailIdx = sReceiveTailIdx; + otPlatUartReceived(&(sReceiveBuffer[sReceiveHeadIdx]), tailIdx - sReceiveHeadIdx); + sReceiveHeadIdx = tailIdx; + } + else + { + tailIdx = CC1352_RECV_CIRC_BUFF_SIZE; + otPlatUartReceived(&(sReceiveBuffer[sReceiveHeadIdx]), tailIdx - sReceiveHeadIdx); + sReceiveHeadIdx = 0; + } + } +} + +/** + * @brief process the transmit side of the buffers + */ +static void processTransmit(void) +{ + otEXPECT(sSendBuffer != NULL); + + for (; sSendLen > 0; sSendLen--) + { + UARTCharPut(UART0_BASE, *sSendBuffer); + sSendBuffer++; + } + + sSendBuffer = NULL; + sSendLen = 0; + otPlatUartSendDone(); + +exit: + return; +} + +/** + * Function documented in platform-cc1352.h + */ +void cc1352UartProcess(void) +{ + processReceive(); + processTransmit(); +} + +/** + * @brief the interrupt handler for the uart interrupt vector + */ +void UART0_intHandler(void) +{ + while (UARTCharsAvail(UART0_BASE)) + { + uint32_t c = UARTCharGet(UART0_BASE); + /* XXX process error flags for this character ?? */ + sReceiveBuffer[sReceiveTailIdx] = (uint8_t)c; + sReceiveTailIdx++; + + if (sReceiveTailIdx >= CC1352_RECV_CIRC_BUFF_SIZE) + { + sReceiveTailIdx = 0; + } + } +} + +#if OPENTHREAD_CONFIG_ENABLE_DEBUG_UART + +/* + * Documented in platform-cc1352.h + */ +void cc1352DebugUartInit(void) +{ + uart_power_control(UART1_BASE, true); + /* + * LaunchPad Pin29 = tx, Pin 30 = rxd + * + * The function IOCPinTypeUart() is hard coded to + * only support UART0 - and does not support UART1. + * + * Thus, these pins are configured using a different way. + */ + IOCPortConfigureSet(IOID_0, IOC_PORT_MCU_UART1_TX, IOC_STD_INPUT); + IOCPortConfigureSet(IOID_1, IOC_PORT_MCU_UART1_RX, IOC_STD_INPUT); + + UARTConfigSetExpClk(UART1_BASE, SysCtrlClockGet(), 115200, + UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE); + UARTEnable(UART1_BASE); +} + +/* This holds the last key pressed */ +static int debug_uart_ungetbuf; + +/* + * Documented in "src/core/common/debug_uart.h" + */ +int otPlatDebugUart_getc(void) +{ + int ch = -1; + + if (otPlatDebugUart_kbhit()) + { + /* get & clear 0x100 bit used below as flag */ + ch = debug_uart_ungetbuf & 0x0ff; + debug_uart_ungetbuf = 0; + } + + return ch; +} + +/* + * Documented in "src/core/common/debug_uart.h" + */ +int otPlatDebugUart_kbhit(void) +{ + int r; + + /* if something is in the unget buf... */ + r = !!debug_uart_ungetbuf; + + if (!r) + { + /* + * Driverlib code returns "-1", or "char" on something + * but it comes with flags in upper bits + */ + r = (int)UARTCharGetNonBlocking(UART1_BASE); + + if (r < 0) + { + r = 0; /* no key pressed */ + } + else + { + /* key was pressed, mask flags + * and set 0x100 bit, to distinguish + * the value "0x00" from "no-key-pressed" + */ + debug_uart_ungetbuf = ((r & 0x0ff) | 0x0100); + + r = 1; /* key pressed */ + } + } + + return r; +} + +/* + * Documented in "src/core/common/debug_uart.h" + */ +void otPlatDebugUart_putchar_raw(int b) +{ + UARTCharPut(UART1_BASE, b); +} + +#endif /* OPENTHREAD_CONFIG_ENABLE_DEBUG_UART */ diff --git a/examples/platforms/cc2650/diag.c b/examples/platforms/cc2650/diag.c index 932bb8cc6..27b1714c8 100644 --- a/examples/platforms/cc2650/diag.c +++ b/examples/platforms/cc2650/diag.c @@ -26,14 +26,17 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include #include + +#include +#include +#include + #include #if OPENTHREAD_ENABLE_DIAG +#include "platform-cc2650.h" /** * Diagnostics mode variables. * diff --git a/examples/platforms/cc2650/misc.c b/examples/platforms/cc2650/misc.c index 69f5f4a44..09676a133 100644 --- a/examples/platforms/cc2650/misc.c +++ b/examples/platforms/cc2650/misc.c @@ -55,7 +55,6 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance) return OT_PLAT_RESET_REASON_EXTERNAL; case RSTSRC_VDDS_LOSS: - case RSTSRC_VDD_LOSS: case RSTSRC_VDDR_LOSS: case RSTSRC_CLK_LOSS: return OT_PLAT_RESET_REASON_CRASH; diff --git a/examples/platforms/cc2650/radio.c b/examples/platforms/cc2650/radio.c index 9deb61444..614158d2d 100644 --- a/examples/platforms/cc2650/radio.c +++ b/examples/platforms/cc2650/radio.c @@ -26,12 +26,15 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include + #include #include "cc2650_radio.h" #include #include #include +#include #include #include /* to seed the CSMA-CA funciton */ diff --git a/examples/platforms/cc2652/Makefile.am b/examples/platforms/cc2652/Makefile.am index b8ee60153..f63e99dc7 100644 --- a/examples/platforms/cc2652/Makefile.am +++ b/examples/platforms/cc2652/Makefile.am @@ -28,58 +28,58 @@ include $(abs_top_nlbuild_autotools_dir)/automake/pre.am -lib_LIBRARIES = libopenthread-cc2652.a +lib_LIBRARIES = libopenthread-cc2652.a # Do not enable -pedantic-errors for cc26xx driverlib -override CFLAGS := $(filter-out -pedantic-errors,$(CFLAGS)) -override CXXFLAGS := $(filter-out -pedantic-errors,$(CXXFLAGS)) +override CFLAGS := $(filter-out -pedantic-errors,$(CFLAGS)) +override CXXFLAGS := $(filter-out -pedantic-errors,$(CXXFLAGS)) -libopenthread_cc2652_a_CPPFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src \ - -I$(top_srcdir)/src/core \ - -I$(top_srcdir)/examples/platforms \ - -I$(top_srcdir)/examples/platforms/cc2652 \ - -I$(top_srcdir)/third_party/ti/devices/cc26x2 \ - -I$(top_srcdir)/third_party/mbedtls/repo/include \ - $(MBEDTLS_CPPFLAGS) \ +libopenthread_cc2652_a_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/core \ + -I$(top_srcdir)/examples/platforms \ + -I$(top_srcdir)/examples/platforms/cc2652 \ + -I$(top_srcdir)/third_party/ti/devices/cc13x2_cc26x2 \ + -I$(top_srcdir)/third_party/mbedtls/repo/include \ + $(MBEDTLS_CPPFLAGS) \ $(NULL) -PLATFORM_SOURCES = \ - alarm.c \ - diag.c \ - flash.c \ - logging.c \ - misc.c \ - platform.c \ - radio.c \ - random.c \ - uart.c \ - crypto/aes_alt.c \ - cc2652_ccfg.c \ - cc2652_startup.c \ - cxx_helpers.c \ +PLATFORM_SOURCES = \ + alarm.c \ + diag.c \ + flash.c \ + logging.c \ + misc.c \ + platform.c \ + radio.c \ + random.c \ + uart.c \ + crypto/aes_alt.c \ + cc2652_ccfg.c \ + cc2652_startup.c \ + cxx_helpers.c \ $(NULL) -libopenthread_cc2652_a_SOURCES = \ - $(PLATFORM_SOURCES) \ +libopenthread_cc2652_a_SOURCES = \ + $(PLATFORM_SOURCES) \ $(NULL) -libopenthread_cc2652_a_DEPENDENCIES = \ - $(top_srcdir)/third_party/ti/devices/cc26x2/driverlib/bin/gcc/driverlib.a \ +libopenthread_cc2652_a_DEPENDENCIES = \ + $(top_srcdir)/third_party/ti/devices/cc13x2_cc26x2/driverlib/bin/gcc/driverlib.a \ $(NULL) -noinst_HEADERS = \ - platform-cc2652.h \ +noinst_HEADERS = \ + platform-cc2652.h \ $(NULL) -PRETTY_FILES = \ - $(PLATFORM_SOURCES) \ - $(noinst_HEADERS) \ +PRETTY_FILES = \ + $(PLATFORM_SOURCES) \ + $(noinst_HEADERS) \ $(NULL) -Dash = - -libopenthread_cc2652_a_LIBADD = \ +Dash = - +libopenthread_cc2652_a_LIBADD = \ $(shell find $(top_builddir)/examples/platforms/utils $(Dash)type f $(Dash)name "*.o") include $(abs_top_nlbuild_autotools_dir)/automake/post.am diff --git a/examples/platforms/cc2652/Makefile.platform.am b/examples/platforms/cc2652/Makefile.platform.am index 67492168f..e8a64cc9d 100644 --- a/examples/platforms/cc2652/Makefile.platform.am +++ b/examples/platforms/cc2652/Makefile.platform.am @@ -30,15 +30,15 @@ # cc2652 platform-specific Makefile # -CPPFLAGS_COMMON += \ - -I$(top_srcdir)/third_party/ti/devices/cc26x2 \ +CPPFLAGS_COMMON += \ + -I$(top_srcdir)/third_party/ti/devices/cc13x2_cc26x2 \ $(NULL) -LDADD_COMMON += \ - $(top_builddir)/examples/platforms/cc2652/libopenthread-cc2652.a \ - $(top_srcdir)/third_party/ti/devices/cc26x2/driverlib/bin/gcc/driverlib.a \ +LDADD_COMMON += \ + $(top_builddir)/examples/platforms/cc2652/libopenthread-cc2652.a \ + $(top_srcdir)/third_party/ti/devices/cc13x2_cc26x2/driverlib/bin/gcc/driverlib.a \ $(NULL) -LDFLAGS_COMMON += \ - -T $(top_srcdir)/third_party/ti/devices/cc26x2/linker_files/cc26x2r1f.lds \ +LDFLAGS_COMMON += \ + -T $(top_srcdir)/third_party/ti/devices/cc13x2_cc26x2/linker_files/cc26x2r1f.lds \ $(NULL) diff --git a/examples/platforms/cc2652/cc2652_ccfg.c b/examples/platforms/cc2652/cc2652_ccfg.c index aea2c046a..7f1e9b641 100644 --- a/examples/platforms/cc2652/cc2652_ccfg.c +++ b/examples/platforms/cc2652/cc2652_ccfg.c @@ -37,8 +37,7 @@ #define SET_CCFG_BL_CONFIG_BL_LEVEL 0x0 // Active low to open boot loader backdoor -#define SET_CCFG_BL_CONFIG_BL_PIN_NUMBER 0x0D // DIO13 (BTN-1 button) on CC2650 LaunchPad Board for boot loader backdoor -// #define SET_CCFG_BL_CONFIG_BL_PIN_NUMBER 0x0B // DIO11 (SELECT button) on CC2650DK (QFN48/7*7) for boot loader backdoor +#define SET_CCFG_BL_CONFIG_BL_PIN_NUMBER 0x0D // DIO13 (BTN-1 button) on CC2652 LaunchPad Board for boot loader backdoor #define SET_CCFG_BL_CONFIG_BL_ENABLE 0xC5 // Enabled boot loader backdoor diff --git a/examples/platforms/cc2652/cc2652_radio.h b/examples/platforms/cc2652/cc2652_radio.h index c797a3d15..07cfa4dfa 100644 --- a/examples/platforms/cc2652/cc2652_radio.h +++ b/examples/platforms/cc2652/cc2652_radio.h @@ -72,22 +72,26 @@ typedef struct output_config uint16_t value; } output_config_t; -/* TODO: update with power measurments */ +/** + * TX Power dBm lookup table from SmartRF Studio 7 2.10.0#94 + */ static const output_config_t rgOutputPower[] = { - { 5, 0x9330}, - { 4, 0x9324}, - { 3, 0x5a1c}, - { 2, 0x4e18}, - { 1, 0x4214}, - { 0, 0x3161}, - { -3, 0x2558}, - { -6, 0x1d52}, - { -9, 0x194e}, - { -12, 0x144b}, - { -15, 0x0ccb}, - { -18, 0x0cc9}, - { -21, 0x0cc7}, + { 5, 0x941e}, + { 4, 0x6c16}, + { 3, 0x5411}, + { 2, 0x440d}, + { 1, 0x385c}, + { 0, 0x3459}, + { -3, 0x2851}, + { -5, 0x224e}, + { -6, 0x204d}, + { -9, 0x0a8d}, + { -10, 0x168c}, + { -12, 0x10a8}, + { -15, 0xc88c}, + { -18, 0x06c9}, + { -21, 0x06c7}, }; #define OUTPUT_CONFIG_COUNT (sizeof(rgOutputPower) / sizeof(rgOutputPower[0])) diff --git a/examples/platforms/cc2652/crypto/cc2652-mbedtls-config.h b/examples/platforms/cc2652/crypto/cc2652-mbedtls-config.h index ced68f81c..5bcf94c76 100644 --- a/examples/platforms/cc2652/crypto/cc2652-mbedtls-config.h +++ b/examples/platforms/cc2652/crypto/cc2652-mbedtls-config.h @@ -2461,7 +2461,7 @@ #define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */ /* Entropy options */ -#define MBEDTLS_ENTROPY_MAX_SOURCES 1 /**< Maximum number of sources supported */ +#define MBEDTLS_ENTROPY_MAX_SOURCES 1 /**< Maximum number of sources supported */ //#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ /* Memory buffer allocator options */ diff --git a/examples/platforms/cc2652/misc.c b/examples/platforms/cc2652/misc.c index 142aa0a17..0550e6599 100644 --- a/examples/platforms/cc2652/misc.c +++ b/examples/platforms/cc2652/misc.c @@ -67,7 +67,6 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance) break; case RSTSRC_VDDS_LOSS: - case RSTSRC_VDD_LOSS: case RSTSRC_VDDR_LOSS: case RSTSRC_CLK_LOSS: ret = OT_PLAT_RESET_REASON_CRASH; diff --git a/examples/platforms/cc2652/radio.c b/examples/platforms/cc2652/radio.c index 31807c5af..86de3c81c 100644 --- a/examples/platforms/cc2652/radio.c +++ b/examples/platforms/cc2652/radio.c @@ -69,13 +69,40 @@ static volatile cc2652_PhyState_t sState; /* set to max transmit power by default */ static output_config_t const *sCurrentOutputPower = &(rgOutputPower[0]); -/* TODO: replace with correct overrides, pre-Alpha */ -/* Overrides for IEEE 802.15.4, differential mode */ +/* Overrides from SmartRF Studio 7 2.10.0#94 */ static uint32_t sIEEEOverrides[] = { - 0x00008403, // Use 48 MHz Crystal - 0x000088C3, // Disabling dynamic DCDC settings control in RX - 0x000088D3, // Disabling dynamic DCDC settings control in TX - 0xFFFFFFFF, // END_OVERRIDE + // override_ieee_802_15_4.xml + // PHY: Use MCE RAM patch, RFE ROM bank 1 + MCE_RFE_OVERRIDE(1, 0, 0, 0, 1, 0), + // Synth: Use 48 MHz crystal, enable extra PLL filtering + (uint32_t)0x02400403, + // Synth: Configure extra PLL filtering + (uint32_t)0x001C8473, + // Synth: Configure synth hardware + (uint32_t)0x00088433, + // Synth: Set minimum RTRIM to 3 + (uint32_t)0x00038793, + // Synth: Configure faster calibration + HW32_ARRAY_OVERRIDE(0x4004, 1), + // Synth: Configure faster calibration + (uint32_t)0x1C0C0618, + // Synth: Configure faster calibration + (uint32_t)0xC00401A1, + // Synth: Configure faster calibration + (uint32_t)0x00010101, + // Synth: Configure faster calibration + (uint32_t)0xC0040141, + // Synth: Configure faster calibration + (uint32_t)0x00214AD3, + // Synth: Decrease synth programming time-out (0x0298 RAT ticks = 166 us) + (uint32_t)0x02980243, + // DC/DC regulator: In Tx, use DCDCCTL5[3:0]=0xC (DITHER_EN=1 and IPEAK=4). In Rx, use DCDCCTL5[3:0]=0xC + // (DITHER_EN=1 and IPEAK=4). + (uint32_t)0xFCFC08C3, + // Rx: Set LNA bias current offset to +15 to saturate trim to max (default: 0) + (uint32_t)0x000F8883, + // override_frontend_id.xml + (uint32_t)0xFFFFFFFF, }; /* diff --git a/examples/platforms/cc2652/uart.c b/examples/platforms/cc2652/uart.c index 97877e603..13fc515f5 100644 --- a/examples/platforms/cc2652/uart.c +++ b/examples/platforms/cc2652/uart.c @@ -82,7 +82,7 @@ static void uart_power_control(uint32_t who_base, int turnon) { /* UART0 is in the SERIAL domain * UART1 is in the PERIPH domain. - * See: ti/devices/cc26x2/driverlib/pcrm.h, line: 658 + * See: ti/devices/cc13x2_cc26x2/driverlib/pcrm.h, line: 658 */ value = (who_base == UART0_BASE) ? PRCM_DOMAIN_SERIAL : PRCM_DOMAIN_PERIPH; PRCMPowerDomainOn(value); diff --git a/include/openthread/platform/toolchain.h b/include/openthread/platform/toolchain.h index 5dfec8221..5aec6762c 100644 --- a/include/openthread/platform/toolchain.h +++ b/include/openthread/platform/toolchain.h @@ -258,6 +258,25 @@ extern "C" { #define OT_UNREACHABLE_CODE(CODE) CODE +#elif defined(__TI_ARM__) + +#include + +#define OT_UNUSED_VARIABLE(VARIABLE) \ + do \ + { \ + if (&VARIABLE == NULL) \ + { \ + } \ + } while (false) + +/* + * #112-D statement is unreachable + * #129-D loop is not reachable + */ +#define OT_UNREACHABLE_CODE(CODE) \ + _Pragma("diag_push") _Pragma("diag_suppress 112") _Pragma("diag_suppress 129") CODE _Pragma("diag_pop") + #else #define OT_UNUSED_VARIABLE(VARIABLE) \ diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index 2ec53a361..f388e5502 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -274,3 +274,4 @@ endif # OPENTHREAD_BUILD_COVERAGE endif # OPENTHREAD_BUILD_TESTS include $(abs_top_nlbuild_autotools_dir)/automake/post.am + diff --git a/third_party/ti/README.md b/third_party/ti/README.md index 5d34822d3..461935802 100644 --- a/third_party/ti/README.md +++ b/third_party/ti/README.md @@ -1,10 +1,11 @@ #CC26XXware ## URL + http://www.ti.com/tool/simplelink-cc26x2-sdk ## Version -`driverlib_cc13xx_cc26xx_3_01_01_17779` +`driverlib_cc13xx_cc26xx_3_30_03_00` ## License @@ -12,7 +13,7 @@ BSD-3-Clause ## License File -[Export Manifest](cc26xxware/cc26xxware_2_24_0x_manifest.html) +[Export Manifest] manifest_driverlib_cc13xx_cc26xx_3_xx_xx.html ## Documentation @@ -20,21 +21,24 @@ This version of cc26xxware is copied from the [SimpleLink CC26x2 Software Development Kit](http://www.ti.com/tool/simplelink-cc26x2-sdk). Modifications were made to the software package to support the GCC Automake pedantic build. -| file | change | -|-----------------------------------------------|------------------------------------------------------------------------------| -| `device/cc26x0/driverlib/bin/gcc/driverlib.a` | Renamed from `driverlib.lib` to allow Automake to recognize the library | -| `device/cc26x2/driverlib/bin/gcc/driverlib.a` | Renamed from `driverlib.lib` to allow Automake to recognize the library | -| `device/cc26x0/driverlib/cpu.h` | GCC asm extensions added to avoid unused variable warning in `CPUbasepriSet` | -| `device/cc26x2/driverlib/cpu.h` | GCC asm extensions added to avoid unused variable warning in `CPUbasepriSet` | -| `device/cc26x0/linker_files/cc26x0f128.lds` | `end` symbol added for GCC stdlib | -| `device/cc26x2/linker_files/cc26x2r1f.lds` | `end` symbol added for GCC stdlib | +Also see: release_notes_driverlib_cc13xx_cc26xx.html + +| file | change | +|-------------------------------------------------------|------------------------------------------------------------------------------| +| `device/cc26x0/driverlib/bin/gcc/driverlib.a` | Renamed from `driverlib.lib` to allow Automake to recognize the library | +| `device/cc13x52_cc26x2/driverlib/bin/gcc/driverlib.a` | Renamed from `driverlib.lib` to allow Automake to recognize the library | +| `device/cc26x0/linker_files/cc26x0f128.lds` | `end` symbol added for GCC stdlib | +| `device/cc13x52_cc26x2/linker_files/cc26x2r1f.lds` | `end` symbol added for GCC stdlib | Documentation can be found within the [SimpleLink CC26x2 Software Development Kit](http://www.ti.com/tool/simplelink-cc26x2-sdk). +**TODO** Update above link + ## Description CC26XXware is the board support library for Texas Instruments' CC26XX line of connected MCUs for developers to easily leverage the hardware capabilities of those platforms. Texas Instruments Incorporated recommends TI-RTOS and its associated drivers for future development. + diff --git a/third_party/ti/devices/DeviceFamily.h b/third_party/ti/devices/DeviceFamily.h index c2a0c3c67..8566650a7 100644 --- a/third_party/ti/devices/DeviceFamily.h +++ b/third_party/ti/devices/DeviceFamily.h @@ -50,77 +50,138 @@ extern "C" { #endif -/* List of DeviceFamily_ID_XYZ values. - * DeviceFamily_ID may be used in the preprocessor for conditional compilation. - * DeviceFamily_ID is set as one of these IDs is set based on the top - * level DeviceFamily_XYZ define. - */ -#define DeviceFamily_ID_CC26X0 0x00000001 -#define DeviceFamily_ID_CC26X0R2 0x00000002 -#define DeviceFamily_ID_CC26X2 0x00000004 -#define DeviceFamily_ID_CC13X0 0x00000100 -#define DeviceFamily_ID_CC13X2 0x00000200 -#define DeviceFamily_ID_CC3200 0x00010000 -#define DeviceFamily_ID_CC3220 0x00020000 -#define DeviceFamily_ID_MSP432P401x 0x01000000 -#define DeviceFamily_ID_MSP432P4x1xI 0x02000000 -#define DeviceFamily_ID_MSP432P4x1xT 0x04000000 - -/* Lookup table that sets DeviceFamily_ID and DeviceFamily_DIRECTORY based on the existence - * of a DeviceFamily_XYZ define. - * If DeviceFamily_XYZ is undefined, a compiler error is thrown. If multiple DeviceFamily_XYZ - * are defined, the first one encountered is used. +/* + * DeviceFamily_ID_XYZ values. * - * Currently supported values of DeviceFamily_XYZ are: - * - DeviceFamily_CC26X0 - * - DeviceFamily_CC26X0R2 - * - DeviceFamily_CC26X2 - * - DeviceFamily_CC13X0 - * - DeviceFamily_CC13X2 - * - DeviceFamily_CC3200 - * - DeviceFamily_CC3220 - * - DeviceFamily_MSP432P401x - * - DeviceFamily_MSP432P4x1 + * DeviceFamily_ID may be used in the preprocessor for conditional compilation. + * DeviceFamily_ID is set to one of these values based on the top level + * DeviceFamily_XYZ define. */ -#if defined(DeviceFamily_CC26X0) +#define DeviceFamily_ID_CC13X0 1 +#define DeviceFamily_ID_CC26X0 2 +#define DeviceFamily_ID_CC26X0R2 3 +#define DeviceFamily_ID_CC13X2_V1 4 +#define DeviceFamily_ID_CC13X2_V2 5 +#define DeviceFamily_ID_CC13X2 DeviceFamily_ID_CC13X2_V1 +#define DeviceFamily_ID_CC26X2_V1 6 +#define DeviceFamily_ID_CC26X2_V2 7 +#define DeviceFamily_ID_CC26X2 DeviceFamily_ID_CC26X2_V1 +#define DeviceFamily_ID_CC3200 8 +#define DeviceFamily_ID_CC3220 9 +#define DeviceFamily_ID_MSP432P401x 10 +#define DeviceFamily_ID_MSP432P4x1xI 11 +#define DeviceFamily_ID_MSP432P4x1xT 12 +#define DeviceFamily_ID_MSP432E401Y 13 +#define DeviceFamily_ID_MSP432E411Y 14 + +/* + * DeviceFamily_PARENT_XYZ values. + * + * DeviceFamily_PARENT may be used in the preprocessor for conditional + * compilation. DeviceFamily_PARENT is set to one of these values based + * on the top-level DeviceFamily_XYZ define. + */ +#define DeviceFamily_PARENT_CC13X0_CC26X0 1 +#define DeviceFamily_PARENT_CC13X2_CC26X2 2 +#define DeviceFamily_PARENT_MSP432P401R 3 +#define DeviceFamily_PARENT_MSP432P4111 4 + +/* + * Lookup table that sets DeviceFamily_ID, DeviceFamily_DIRECTORY, and + * DeviceFamily_PARENT based on the DeviceFamily_XYZ define. + * If DeviceFamily_XYZ is undefined, a compiler error is thrown. If + * multiple DeviceFamily_XYZ are defined, the first one encountered is used. + */ +#if defined(DeviceFamily_CC13X0) + #define DeviceFamily_ID DeviceFamily_ID_CC13X0 + #define DeviceFamily_DIRECTORY cc13x0 + #define DeviceFamily_PARENT DeviceFamily_PARENT_CC13X0_CC26X0 + +#elif defined(DeviceFamily_CC13X2) + #define DeviceFamily_ID DeviceFamily_ID_CC13X2 + #define DeviceFamily_DIRECTORY cc13x2_cc26x2_v1 + #define DeviceFamily_PARENT DeviceFamily_PARENT_CC13X2_CC26X2 + +#elif defined(DeviceFamily_CC13X2_V1) + #define DeviceFamily_ID DeviceFamily_ID_CC13X2_V1 + #define DeviceFamily_DIRECTORY cc13x2_cc26x2_v1 + #define DeviceFamily_PARENT DeviceFamily_PARENT_CC13X2_CC26X2 + +#elif defined(DeviceFamily_CC13X2_V2) + #define DeviceFamily_ID DeviceFamily_ID_CC13X2_V2 + #define DeviceFamily_DIRECTORY cc13x2_cc26x2_v2 + #define DeviceFamily_PARENT DeviceFamily_PARENT_CC13X2_CC26X2 + +#elif defined(DeviceFamily_CC26X0) #define DeviceFamily_ID DeviceFamily_ID_CC26X0 #define DeviceFamily_DIRECTORY cc26x0 + #define DeviceFamily_PARENT DeviceFamily_PARENT_CC13X0_CC26X0 + #elif defined(DeviceFamily_CC26X0R2) #define DeviceFamily_ID DeviceFamily_ID_CC26X0R2 #define DeviceFamily_DIRECTORY cc26x0r2 + #define DeviceFamily_PARENT DeviceFamily_PARENT_CC13X0_CC26X0 + #elif defined(DeviceFamily_CC26X2) #define DeviceFamily_ID DeviceFamily_ID_CC26X2 - #define DeviceFamily_DIRECTORY cc26x2 -#elif defined(DeviceFamily_CC13X0) - #define DeviceFamily_ID DeviceFamily_ID_CC13X0 - #define DeviceFamily_DIRECTORY cc13x0 -#elif defined(DeviceFamily_CC13X2) - #define DeviceFamily_ID DeviceFamily_ID_CC13X2 - #define DeviceFamily_DIRECTORY cc26x2 + #define DeviceFamily_DIRECTORY cc13x2_cc26x2_v1 + #define DeviceFamily_PARENT DeviceFamily_PARENT_CC13X2_CC26X2 + +#elif defined(DeviceFamily_CC26X2_V1) + #define DeviceFamily_ID DeviceFamily_ID_CC26X2_V1 + #define DeviceFamily_DIRECTORY cc13x2_cc26x2_v1 + #define DeviceFamily_PARENT DeviceFamily_PARENT_CC13X2_CC26X2 + +#elif defined(DeviceFamily_CC26X2_V2) + #define DeviceFamily_ID DeviceFamily_ID_CC26X2_V2 + #define DeviceFamily_DIRECTORY cc13x2_cc26x2_v2 + #define DeviceFamily_PARENT DeviceFamily_PARENT_CC13X2_CC26X2 + #elif defined(DeviceFamily_CC3200) #define DeviceFamily_ID DeviceFamily_ID_CC3200 #define DeviceFamily_DIRECTORY cc32xx + #elif defined(DeviceFamily_CC3220) #define DeviceFamily_ID DeviceFamily_ID_CC3220 #define DeviceFamily_DIRECTORY cc32xx + #elif defined(DeviceFamily_MSP432P401x) || defined(__MSP432P401R__) #define DeviceFamily_ID DeviceFamily_ID_MSP432P401x #define DeviceFamily_DIRECTORY msp432p4xx + #define DeviceFamily_PARENT DeviceFamily_PARENT_MSP432P401R #if !defined(__MSP432P401R__) #define __MSP432P401R__ #endif + #elif defined(DeviceFamily_MSP432P4x1xI) #define DeviceFamily_ID DeviceFamily_ID_MSP432P4x1xI #define DeviceFamily_DIRECTORY msp432p4xx + #define DeviceFamily_PARENT DeviceFamily_PARENT_MSP432P4111 #if !defined(__MSP432P4111__) #define __MSP432P4111__ #endif + #elif defined(DeviceFamily_MSP432P4x1xT) #define DeviceFamily_ID DeviceFamily_ID_MSP432P4x1xT #define DeviceFamily_DIRECTORY msp432p4xx + #define DeviceFamily_PARENT DeviceFamily_PARENT_MSP432P4111 #if !defined(__MSP432P4111__) #define __MSP432P4111__ #endif + +#elif defined(DeviceFamily_MSP432E401Y) + #define DeviceFamily_ID DeviceFamily_ID_MSP432E401Y + #define DeviceFamily_DIRECTORY msp432e4 + #if !defined(__MSP432E401Y__) + #define __MSP432E401Y__ + #endif + +#elif defined(DeviceFamily_MSP432E411Y) + #define DeviceFamily_ID DeviceFamily_ID_MSP432E411Y + #define DeviceFamily_DIRECTORY msp432e4 + #if !defined(__MSP432E411Y__) + #define __MSP432E411Y__ + #endif #else #error "DeviceFamily_XYZ undefined. You must defined DeviceFamily_XYZ!" #endif @@ -128,11 +189,12 @@ extern "C" { /*! * @brief Macro to include correct driverlib path. * - * @pre DeviceFamily_XYZ which sets DeviceFamily_DIRECTORY must be defined first. + * @pre DeviceFamily_XYZ which sets DeviceFamily_DIRECTORY must be defined + * first. * - * @param x A token containing the path of the file to include based on the root - * device folder. The preceding forward slash must be omitted. - * For example: + * @param x A token containing the path of the file to include based on + * the root device folder. The preceding forward slash must be + * omitted. For example: * - #include DeviceFamily_constructPath(inc/hw_memmap.h) * - #include DeviceFamily_constructPath(driverlib/ssi.h) * diff --git a/third_party/ti/devices/cc26x2/driverlib/adi.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/adi.c similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/adi.c rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/adi.c diff --git a/third_party/ti/devices/cc26x2/driverlib/adi.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/adi.h similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/adi.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/adi.h diff --git a/third_party/ti/devices/cc26x2/driverlib/adi_doc.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/adi_doc.h similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/adi_doc.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/adi_doc.h diff --git a/third_party/ti/devices/cc26x2/driverlib/aes.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aes.c similarity index 60% rename from third_party/ti/devices/cc26x2/driverlib/aes.c rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aes.c index 83c0f583a..43c030c92 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aes.c +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aes.c @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: crypto.c -* Revised: 2017-03-29 13:49:36 +0200 (Wed, 29 Mar 2017) -* Revision: 48751 +* Revised: 2018-05-08 10:29:36 +0200 (Tue, 08 May 2018) +* Revision: 51973 * * Description: Driver for the aes functions of the crypto module * @@ -47,24 +47,32 @@ #if !defined(DOXYGEN) #undef AESStartDMAOperation #define AESStartDMAOperation NOROM_AESStartDMAOperation - #undef AESLoadInitializationVector - #define AESLoadInitializationVector NOROM_AESLoadInitializationVector + #undef AESSetInitializationVector + #define AESSetInitializationVector NOROM_AESSetInitializationVector + #undef AESWriteCCMInitializationVector + #define AESWriteCCMInitializationVector NOROM_AESWriteCCMInitializationVector #undef AESReadTag #define AESReadTag NOROM_AESReadTag + #undef AESVerifyTag + #define AESVerifyTag NOROM_AESVerifyTag #undef AESWriteToKeyStore #define AESWriteToKeyStore NOROM_AESWriteToKeyStore #undef AESReadFromKeyStore #define AESReadFromKeyStore NOROM_AESReadFromKeyStore #undef AESWaitForIRQFlags #define AESWaitForIRQFlags NOROM_AESWaitForIRQFlags + #undef AESConfigureCCMCtrl + #define AESConfigureCCMCtrl NOROM_AESConfigureCCMCtrl #endif + + //***************************************************************************** // -// Load the initialisation vector. +// Load the initialization vector. // //***************************************************************************** -void AESLoadInitializationVector(uint32_t *initializationVector) +void AESSetInitializationVector(const uint32_t *initializationVector) { // Write initialization vector to the aes registers HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = initializationVector[0]; @@ -78,15 +86,14 @@ void AESLoadInitializationVector(uint32_t *initializationVector) // Start a crypto DMA operation. // //***************************************************************************** -void AESStartDMAOperation(uint8_t *channel0Addr, uint32_t channel0Length, uint8_t *channel1Addr, uint32_t channel1Length) +void AESStartDMAOperation(const uint8_t *channel0Addr, uint32_t channel0Length, uint8_t *channel1Addr, uint32_t channel1Length) { - - // Clear any outstanding events. - HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = CRYPTO_IRQCLR_RESULT_AVAIL_M | CRYPTO_IRQEN_DMA_IN_DONE_M; // This might need AES_IRQEN_DMA_IN_DONE as well - - while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE_M | CRYPTO_IRQSTAT_RESULT_AVAIL_M)); - if (channel0Length && channel0Addr) { + // We actually want to perform an operation. Clear any outstanding events. + HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = CRYPTO_IRQCLR_RESULT_AVAIL_M | CRYPTO_IRQEN_DMA_IN_DONE_M; // This might need AES_IRQEN_DMA_IN_DONE as well + + while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE_M | CRYPTO_IRQSTAT_RESULT_AVAIL_M)); + // Configure the DMA controller - enable both DMA channels. HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1; @@ -122,15 +129,16 @@ uint32_t AESWaitForIRQFlags(uint32_t irqFlags) do { CPUdelay(1); } - while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & irqFlags & (CRYPTO_IRQSTAT_DMA_IN_DONE_M | CRYPTO_IRQSTAT_RESULT_AVAIL_M))); + while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & irqFlags & (CRYPTO_IRQSTAT_DMA_IN_DONE_M | + CRYPTO_IRQSTAT_RESULT_AVAIL_M | + CRYPTO_IRQSTAT_DMA_BUS_ERR_M | + CRYPTO_IRQSTAT_KEY_ST_WR_ERR_M))); // Save the IRQ trigger source - irqTrigger = HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT); + irqTrigger = HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & irqFlags; // Clear IRQ flags - HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = irqFlags; - - while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & irqFlags & (CRYPTO_IRQSTAT_DMA_IN_DONE_M | CRYPTO_IRQSTAT_RESULT_AVAIL_M)); + HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = irqTrigger; return irqTrigger; } @@ -140,7 +148,7 @@ uint32_t AESWaitForIRQFlags(uint32_t irqFlags) // Transfer a key from CM3 memory to a key store location. // //***************************************************************************** -uint32_t AESWriteToKeyStore(uint8_t *aesKey, uint32_t aesKeySizeBytes, uint32_t keyStoreArea) +uint32_t AESWriteToKeyStore(const uint8_t *aesKey, uint32_t aesKeyLength, uint32_t keyStoreArea) { // Check the arguments. ASSERT((keyStoreArea == AES_KEY_AREA_0) || @@ -152,13 +160,13 @@ uint32_t AESWriteToKeyStore(uint8_t *aesKey, uint32_t aesKeySizeBytes, uint32_t (keyStoreArea == AES_KEY_AREA_6) || (keyStoreArea == AES_KEY_AREA_7)); - ASSERT((aesKeySizeBytes == AES_128_KEY_LENGTH_BYTES) || - (aesKeySizeBytes == AES_192_KEY_LENGTH_BYTES) || - (aesKeySizeBytes == AES_256_KEY_LENGTH_BYTES)); + ASSERT((aesKeyLength == AES_128_KEY_LENGTH_BYTES) || + (aesKeyLength == AES_192_KEY_LENGTH_BYTES) || + (aesKeyLength == AES_256_KEY_LENGTH_BYTES)); uint32_t keySize = 0; - switch (aesKeySizeBytes) { + switch (aesKeyLength) { case AES_128_KEY_LENGTH_BYTES: keySize = CRYPTO_KEYSIZE_SIZE_128_BIT; break; @@ -196,16 +204,20 @@ uint32_t AESWriteToKeyStore(uint8_t *aesKey, uint32_t aesKeySizeBytes, uint32_t } // Enable key to write (e.g. Key 0). - HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITEAREA) = (1 << keyStoreArea); + HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITEAREA) = 1 << keyStoreArea; // Total key length in bytes (16 for 1 x 128-bit key and 32 for 1 x 256-bit key). - AESStartDMAOperation(aesKey, aesKeySizeBytes, 0, 0); + AESStartDMAOperation(aesKey, aesKeyLength, 0, 0); // Wait for the DMA operation to complete. - uint32_t irqTrigger = AESWaitForIRQFlags(CRYPTO_IRQCLR_DMA_IN_DONE | CRYPTO_IRQCLR_RESULT_AVAIL | CRYPTO_IRQSTAT_DMA_BUS_ERR | CRYPTO_IRQSTAT_KEY_ST_WR_ERR); + uint32_t irqTrigger = AESWaitForIRQFlags(CRYPTO_IRQCLR_RESULT_AVAIL | CRYPTO_IRQCLR_DMA_IN_DONE | CRYPTO_IRQSTAT_DMA_BUS_ERR | CRYPTO_IRQSTAT_KEY_ST_WR_ERR); - // If we correctly transfered the key into the keystore, return success. - if ((irqTrigger & (CRYPTO_IRQSTAT_DMA_BUS_ERR_M | CRYPTO_IRQSTAT_KEY_ST_WR_ERR_M)) && !(HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) & (1 << keyStoreArea))) { + // Re-enable interrupts globally. + IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ); + IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ); + + // If we had a bus error or the key is not in the CRYPTO_O_KEYWRITTENAREA, return an error. + if ((irqTrigger & (CRYPTO_IRQSTAT_DMA_BUS_ERR_M | CRYPTO_IRQSTAT_KEY_ST_WR_ERR_M)) || !(HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) & (1 << keyStoreArea))) { // There was an error in writing to the keyStore. return AES_KEYSTORE_ERROR; } @@ -258,21 +270,102 @@ uint32_t AESReadFromKeyStore(uint32_t keyStoreArea) //***************************************************************************** // -// Read the tag after a completed CCM or CBC-MAC operation. +// Read the tag after a completed CCM, GCM, or CBC-MAC operation. // //***************************************************************************** -uint32_t AESReadTag(uint32_t *tag) +uint32_t AESReadTag(uint8_t *tag, uint32_t tagLength) { - // If the tag is not ready, return an error code. - if (!(HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) & CRYPTO_AESCTL_SAVED_CONTEXT_RDY_M)) { - return AES_TAG_NOT_READY; - } + // The intermediate array is used instead of a caller-provided one + // to enable a simple API with no unintuitive alignment or size requirements. + // This is a trade-off of stack-depth vs ease-of-use that came out on the + // ease-of-use side. + uint32_t computedTag[AES_BLOCK_SIZE / sizeof(uint32_t)]; - // Read tag - tag[0] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT0); - tag[1] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT1); - tag[2] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT2); - tag[3] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT3); + // Wait until the computed tag is ready. + while (!(HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) & CRYPTO_AESCTL_SAVED_CONTEXT_RDY_M)); + + // Read computed tag out from the HW registers + // Need to read out all 128 bits in four reads to correctly clear CRYPTO_AESCTL_SAVED_CONTEXT_RDY flag + computedTag[0] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT0); + computedTag[1] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT1); + computedTag[2] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT2); + computedTag[3] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT3); + + memcpy(tag, computedTag, tagLength); return AES_SUCCESS; } + +//***************************************************************************** +// +// Verify the provided tag against the computed tag after a completed CCM or +// GCM operation. +// +//***************************************************************************** +uint32_t AESVerifyTag(const uint8_t *tag, uint32_t tagLength) +{ + uint32_t resultStatus; + // The intermediate array is allocated on the stack to ensure users do not + // point the tag they provide and the one computed at the same location. + // That would cause memcmp to compare an array against itself. We could add + // a check that verifies that the arrays are not the same. If we did that and + // modified AESReadTag to just copy all 128 bits into a provided array, + // we could save 16 bytes of stack space while making the API much more + // complicated. + uint8_t computedTag[AES_BLOCK_SIZE]; + + resultStatus = AESReadTag(computedTag, tagLength); + + if (resultStatus != AES_SUCCESS) { + return resultStatus; + } + + resultStatus = memcmp(computedTag, tag, tagLength); + + if (resultStatus != 0) { + return AES_TAG_VERIFICATION_FAILED; + } + + return AES_SUCCESS; +} + +//***************************************************************************** +// +// Configure the AES module for CCM mode +// +//***************************************************************************** +void AESConfigureCCMCtrl(uint32_t nonceLength, uint32_t macLength, bool encrypt) +{ + uint32_t ctrlVal = 0; + + ctrlVal = ((15 - nonceLength - 1) << CRYPTO_AESCTL_CCM_L_S); + if ( macLength >= 2 ) { + ctrlVal |= ((( macLength - 2 ) >> 1 ) << CRYPTO_AESCTL_CCM_M_S ); + } + ctrlVal |= CRYPTO_AESCTL_CCM | + CRYPTO_AESCTL_CTR | + CRYPTO_AESCTL_SAVE_CONTEXT | + CRYPTO_AESCTL_CTR_WIDTH_128_BIT; + ctrlVal |= encrypt ? CRYPTO_AESCTL_DIR : 0; + + AESSetCtrl(ctrlVal); +} + +//***************************************************************************** +// +// Configure an IV for CCM mode of operation +// +//***************************************************************************** +void AESWriteCCMInitializationVector(const uint8_t *nonce, uint32_t nonceLength) +{ + union { + uint32_t word[4]; + uint8_t byte[16]; + } initializationVector = {{0}}; + + initializationVector.byte[0] = 15 - nonceLength - 1; + + memcpy(&(initializationVector.byte[1]), nonce, nonceLength); + + AESSetInitializationVector(initializationVector.word); +} diff --git a/third_party/ti/devices/cc26x2/driverlib/aes.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aes.h similarity index 73% rename from third_party/ti/devices/cc26x2/driverlib/aes.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aes.h index 14e848fb7..636337895 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aes.h +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aes.h @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aes.h -* Revised: 2017-03-29 13:20:12 +0200 (Wed, 29 Mar 2017) -* Revision: 48750 +* Revised: 2018-04-17 14:54:06 +0200 (Tue, 17 Apr 2018) +* Revision: 51890 * * Description: AES header file. * @@ -61,6 +61,7 @@ extern "C" #include #include +#include #include "../inc/hw_types.h" #include "../inc/hw_memmap.h" #include "../inc/hw_ints.h" @@ -84,13 +85,17 @@ extern "C" //***************************************************************************** #if !defined(DOXYGEN) #define AESStartDMAOperation NOROM_AESStartDMAOperation - #define AESLoadInitializationVector NOROM_AESLoadInitializationVector + #define AESSetInitializationVector NOROM_AESSetInitializationVector + #define AESWriteCCMInitializationVector NOROM_AESWriteCCMInitializationVector #define AESReadTag NOROM_AESReadTag + #define AESVerifyTag NOROM_AESVerifyTag #define AESWriteToKeyStore NOROM_AESWriteToKeyStore #define AESReadFromKeyStore NOROM_AESReadFromKeyStore #define AESWaitForIRQFlags NOROM_AESWaitForIRQFlags + #define AESConfigureCCMCtrl NOROM_AESConfigureCCMCtrl #endif + //***************************************************************************** // // Values that can be passed to AESIntEnable, AESIntDisable, and AESIntClear @@ -119,6 +124,7 @@ extern "C" #define AES_DMA_BUSY 3 #define AES_DMA_ERROR 4 #define AES_TAG_NOT_READY 5 +#define AES_TAG_VERIFICATION_FAILED 6 // Key store module defines #define AES_IV_LENGTH_BYTES 16 @@ -127,7 +133,7 @@ extern "C" #define AES_192_KEY_LENGTH_BYTES (192 / 8) #define AES_256_KEY_LENGTH_BYTES (256 / 8) -#define AES_ECB_BLOCK_SIZE 16 +#define AES_BLOCK_SIZE 16 // DMA status codes #define AES_DMA_CHANNEL0_ACTIVE CRYPTO_DMASTAT_CH0_ACT_M @@ -182,32 +188,32 @@ extern "C" //! transfer. It is also used by the hardware module as a signal to //! begin the encryption, decryption, or MAC operation. //! -//! \param channel0Addr A pointer to the address channel 0 shall use. +//! \param [in] channel0Addr A pointer to the address channel 0 shall use. //! -//! \param channel0Length Length of the data in bytes to be read from or -//! written to at channel0Addr. Set to 0 to not set up -//! this channel. Permitted ranges are mode dependent -//! and displayed below. -//! - ECB: [16] -//! - CBC: [1, sizeof(RAM)] -//! - CBC-MAC: [1, sizeof(RAM)] -//! - CCM: [1, sizeof(RAM)] +//! \param [in] channel0Length Length of the data in bytes to be read from or +//! written to at channel0Addr. Set to 0 to not set up +//! this channel. Permitted ranges are mode dependent +//! and displayed below. +//! - ECB: [16] +//! - CBC: [1, sizeof(RAM)] +//! - CBC-MAC: [1, sizeof(RAM)] +//! - CCM: [1, sizeof(RAM)] //! -//! \param channel1Addr A pointer to the address channel 1 shall use. +//! \param [out] channel1Addr A pointer to the address channel 1 shall use. //! -//! \param channel1Length Length of the data in bytes to be read from or -//! written to at channel1Addr. Set to 0 to not set up -//! this channel.Permitted ranges are mode dependent -//! and displayed below. -//! - ECB: [16] -//! - CBC: [1, sizeof(RAM)] -//! - CBC-MAC: [1, sizeof(RAM)] -//! - CCM: [1, sizeof(RAM)] +//! \param [in] channel1Length Length of the data in bytes to be read from or +//! written to at channel1Addr. Set to 0 to not set up +//! this channel.Permitted ranges are mode dependent +//! and displayed below. +//! - ECB: [16] +//! - CBC: [1, sizeof(RAM)] +//! - CBC-MAC: [1, sizeof(RAM)] +//! - CCM: [1, sizeof(RAM)] //! //! \return None // //***************************************************************************** -extern void AESStartDMAOperation(uint8_t *channel0Addr, uint32_t channel0Length, uint8_t *channel1Addr, uint32_t channel1Length); +extern void AESStartDMAOperation(const uint8_t *channel0Addr, uint32_t channel0Length, uint8_t *channel1Addr, uint32_t channel1Length); //***************************************************************************** // @@ -241,29 +247,68 @@ extern void AESStartDMAOperation(uint8_t *channel0Addr, uint32_t channel0Length, //! } //! \endcode //! -//! \param initializationVector Pointer to an array with four 32-bit elements -//! to be used as initialization vector. -//! Elements of array must be word aligned in memory. +//! \param [in] initializationVector Pointer to an array with four 32-bit elements +//! to be used as initialization vector. +//! Elements of array must be word aligned in memory. //! //! \return None // //***************************************************************************** -extern void AESLoadInitializationVector(uint32_t *initializationVector); +extern void AESSetInitializationVector(const uint32_t *initializationVector); + +//***************************************************************************** +// +//! \brief Generate and load the initialization vector for a CCM operation. +//! +//! +//! \param [in] nonce Pointer to a nonce of length \c nonceLength. +//! +//! \param [in] nonceLength Number of bytes to copy from \c nonce when creating +//! the CCM IV. The L-value is also derived from it. +//! +//! \return None +// +//***************************************************************************** +extern void AESWriteCCMInitializationVector(const uint8_t *nonce, uint32_t nonceLength); //***************************************************************************** // //! \brief Read the tag out from the crypto module. //! -//! \param tag Pointer to an array with four 32-bit elements -//! to be used as initialization vector. -//! Elements of array must be word aligned in memory. +//! This function copies the \c tagLength bytes from the tag calculated by the +//! crypto module in CCM, GCM, or CBC-MAC mode to \c tag. +//! +//! \param [out] tag Pointer to an array of \c tagLength bytes. +//! +//! \param [in] tagLength Number of bytes to copy to \c tag. //! //! \return Returns a status code depending on the result of the transfer. //! - \ref AES_TAG_NOT_READY if the tag is not ready yet //! - \ref AES_SUCCESS otherwise // //***************************************************************************** -extern uint32_t AESReadTag(uint32_t *tag); +extern uint32_t AESReadTag(uint8_t *tag, uint32_t tagLength); + +//***************************************************************************** +// +//! \brief Verifies the provided \c tag against calculated one +//! +//! This function compares the provided tag against the tag calculated by the +//! crypto module during the last CCM, GCM, or CBC-MAC +//! +//! This function copies the \c tagLength bytes from the tag calculated by the +//! crypto module in CCM, GCM, or CBC-MAC mode to \c tag. +//! +//! \param [in] tag Pointer to an array of \c tagLength bytes. +//! +//! \param [in] tagLength Number of bytes to compare. +//! +//! \return Returns a status code depending on the result of the transfer. +//! - \ref AES_TAG_VERIFICATION_FAILED if the verification failed +//! - \ref AES_SUCCESS otherwise +// +//***************************************************************************** +extern uint32_t AESVerifyTag(const uint8_t *tag, uint32_t tagLength); //***************************************************************************** // @@ -271,25 +316,25 @@ extern uint32_t AESReadTag(uint32_t *tag); //! //! The crypto DMA transfers the key and function does not return until //! the operation completes. -//! The keyStore can only contain valid keys of one \c aesKeySizeBytes at +//! The keyStore can only contain valid keys of one \c aesKeyLength at //! any one point in time. The keyStore cannot contain both 128-bit and -//! 256-bit keys simultaneously. When a key of a different \c aesKeySizeBytes -//! from the previous \c aesKeySizeBytes is loaded, all previous keys are +//! 256-bit keys simultaneously. When a key of a different \c aesKeyLength +//! from the previous \c aesKeyLength is loaded, all previous keys are //! invalidated. //! -//! \param aesKey Pointer to key. Does not need to be word-aligned. +//! \param [in] aesKey Pointer to key. Does not need to be word-aligned. //! -//! \param aesKeySizeBytes The key size in bytes. Currently, 128-bit, 192-bit, -//! and 256-bit keys are supported. +//! \param [in] aesKeyLength The key size in bytes. Currently, 128-bit, 192-bit, +//! and 256-bit keys are supported. //! - \ref AES_128_KEY_LENGTH_BYTES //! - \ref AES_192_KEY_LENGTH_BYTES //! - \ref AES_256_KEY_LENGTH_BYTES //! -//! \param keyStoreArea The key store area to transfer the key to. -//! When using 128-bit keys, only the specified key store -//! area will be occupied. -//! When using 256-bit or 192-bit keys, two consecutive key areas -//! are used to store the key. +//! \param [in] keyStoreArea The key store area to transfer the key to. +//! When using 128-bit keys, only the specified key store +//! area will be occupied. +//! When using 256-bit or 192-bit keys, two consecutive key areas +//! are used to store the key. //! - \ref AES_KEY_AREA_0 //! - \ref AES_KEY_AREA_1 //! - \ref AES_KEY_AREA_2 @@ -322,7 +367,7 @@ extern uint32_t AESReadTag(uint32_t *tag); //! \sa AESReadFromKeyStore // //***************************************************************************** -extern uint32_t AESWriteToKeyStore(uint8_t *aesKey, uint32_t aesKeySizeBytes, uint32_t keyStoreArea); +extern uint32_t AESWriteToKeyStore(const uint8_t *aesKey, uint32_t aesKeyLength, uint32_t keyStoreArea); //***************************************************************************** // @@ -331,12 +376,12 @@ extern uint32_t AESWriteToKeyStore(uint8_t *aesKey, uint32_t aesKeySizeBytes, ui //! //! The function polls until the transfer is complete. //! -//! \param keyStoreArea The key store area to transfer the key from. When using -//! 256-bit keys, either of the occupied key areas may be -//! specified to load the key. There is no need to specify -//! the length of the key here as the key store keeps track -//! of how long a key associated with any valid key area is -//! and where is starts. +//! \param [in] keyStoreArea The key store area to transfer the key from. When using +//! 256-bit keys, either of the occupied key areas may be +//! specified to load the key. There is no need to specify +//! the length of the key here as the key store keeps track +//! of how long a key associated with any valid key area is +//! and where is starts. //! - \ref AES_KEY_AREA_0 //! - \ref AES_KEY_AREA_1 //! - \ref AES_KEY_AREA_2 @@ -372,10 +417,10 @@ extern uint32_t AESReadFromKeyStore(uint32_t keyStoreArea); //! always be included in \c irqFlags and will always be returned together //! with any error codes. //! -//! \param irqFlags IRQ flags to poll and mask that the status register will be -//! masked with. May consist of any bitwise OR of the flags -//! below that includes at least one of -//! \ref AES_DMA_IN_DONE or \ref AES_RESULT_RDY : +//! \param [in] irqFlags IRQ flags to poll and mask that the status register will be +//! masked with. May consist of any bitwise OR of the flags +//! below that includes at least one of +//! \ref AES_DMA_IN_DONE or \ref AES_RESULT_RDY : //! - \ref AES_DMA_IN_DONE //! - \ref AES_RESULT_RDY //! - \ref AES_DMA_BUS_ERR @@ -393,12 +438,29 @@ extern uint32_t AESReadFromKeyStore(uint32_t keyStoreArea); //***************************************************************************** extern uint32_t AESWaitForIRQFlags(uint32_t irqFlags); +//***************************************************************************** +// +//! \brief Configure AES engine for CCM operation. +//! +//! \param [in] nonceLength Length of the nonce. Must be <= 14. +//! +//! \param [in] macLength Length of the MAC. Must be <= 16. +//! +//! \param [in] encrypt Whether to set up an encrypt or decrypt operation. +//! - true: encrypt +//! - false: decrypt +//! +//! \return None +// +//***************************************************************************** +extern void AESConfigureCCMCtrl(uint32_t nonceLength, uint32_t macLength, bool encrypt); + //***************************************************************************** // //! \brief Invalidate a key in the key store //! -//! \param keyStoreArea is the entry in the key store to invalidate. This -//! permanently deletes the key from the key store. +//! \param [in] keyStoreArea is the entry in the key store to invalidate. This +//! permanently deletes the key from the key store. //! - \ref AES_KEY_AREA_0 //! - \ref AES_KEY_AREA_1 //! - \ref AES_KEY_AREA_2 @@ -430,8 +492,8 @@ __STATIC_INLINE void AESInvalidateKey(uint32_t keyStoreArea) // //! \brief Select type of operation //! -//! \param algorithm Flags that specify which type of operation the crypto -//! module shall perform. The flags are mutually exclusive. +//! \param [in] algorithm Flags that specify which type of operation the crypto +//! module shall perform. The flags are mutually exclusive. //! - 0 : Reset the module //! - \ref AES_ALGSEL_AES //! - \ref AES_ALGSEL_TAG @@ -442,9 +504,9 @@ __STATIC_INLINE void AESInvalidateKey(uint32_t keyStoreArea) //***************************************************************************** __STATIC_INLINE void AESSelectAlgorithm(uint32_t algorithm) { - ASSERT((keyStoreEntry == AES_ALGSEL_AES) || - (keyStoreEntry == AES_ALGSEL_AES | AES_ALGSEL_TAG) || - (keyStoreEntry == AES_ALGSEL_KEY_STORE)); + ASSERT((algorithm == AES_ALGSEL_AES) || + (algorithm == AES_ALGSEL_AES | AES_ALGSEL_TAG) || + (algorithm == AES_ALGSEL_KEY_STORE)); HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = algorithm; } @@ -457,12 +519,12 @@ __STATIC_INLINE void AESSelectAlgorithm(uint32_t algorithm) //! register. The relevant field names have the format: //! - CRYPTO_AESCTL_[field name] //! -//! \param ctrlMask Specifies which register fields shall be set. +//! \param [in] ctrlMask Specifies which register fields shall be set. //! //! \return None // //***************************************************************************** -__STATIC_INLINE void AESSetupCtrl(uint32_t ctrlMask) +__STATIC_INLINE void AESSetCtrl(uint32_t ctrlMask) { HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = ctrlMask; } @@ -474,22 +536,22 @@ __STATIC_INLINE void AESSetupCtrl(uint32_t ctrlMask) //! Despite specifying it here, the crypto DMA must still be //! set up with the correct data length. //! -//! \param length Data length in bytes. If this -//! value is set to 0, only authentication of the AAD is -//! performed in CCM-mode and AESWriteAuthLength() must be set to -//! >0. -//! Range depends on the mode: -//! - ECB: [16] -//! - CBC: [1, sizeof(RAM)] -//! - CBC-MAC: [1, sizeof(RAM)] -//! - CCM: [0, sizeof(RAM)] +//! \param [in] length Data length in bytes. If this +//! value is set to 0, only authentication of the AAD is +//! performed in CCM-mode and AESWriteAuthLength() must be set to +//! >0. +//! Range depends on the mode: +//! - ECB: [16] +//! - CBC: [1, sizeof(RAM)] +//! - CBC-MAC: [1, sizeof(RAM)] +//! - CCM: [0, sizeof(RAM)] //! //! \return None //! //! \sa AESWriteAuthLength // //***************************************************************************** -__STATIC_INLINE void AESWriteDataLength(uint32_t length) +__STATIC_INLINE void AESSetDataLength(uint32_t length) { HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = length; HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1) = 0; @@ -502,21 +564,21 @@ __STATIC_INLINE void AESWriteDataLength(uint32_t length) //! Despite specifying it here, the crypto DMA must still be set up with //! the correct AAD length. //! -//! \param length Specifies how long the AAD is in a CCM operation. In CCM mode, -//! set this to 0 if no AAD is required. If set to 0, -//! AESWriteDataLength() must be set to >0. -//! Range depends on the mode: -//! - ECB: Do not call. -//! - CBC: [0] -//! - CBC-MAC: [0] -//! - CCM: [0, sizeof(RAM)] +//! \param [in] length Specifies how long the AAD is in a CCM operation. In CCM mode, +//! set this to 0 if no AAD is required. If set to 0, +//! AESWriteDataLength() must be set to >0. +//! Range depends on the mode: +//! - ECB: Do not call. +//! - CBC: [0] +//! - CBC-MAC: [0] +//! - CCM: [0, sizeof(RAM)] //! //! \return None //! //! \sa AESWriteDataLength // //***************************************************************************** -__STATIC_INLINE void AESWriteAuthLength(uint32_t length) +__STATIC_INLINE void AESSetAuthLength(uint32_t length) { HWREG(CRYPTO_BASE + CRYPTO_O_AESAUTHLEN) = length; } @@ -529,7 +591,7 @@ __STATIC_INLINE void AESWriteAuthLength(uint32_t length) //! sources that are enabled can be reflected to the processor interrupt. //! Disabled sources have no effect on the processor. //! -//! \param intFlags is the bitwise OR of the interrupt sources to be enabled. +//! \param [in] intFlags is the bitwise OR of the interrupt sources to be enabled. //! - \ref AES_DMA_IN_DONE //! - \ref AES_RESULT_RDY //! @@ -557,7 +619,7 @@ __STATIC_INLINE void AESIntEnable(uint32_t intFlags) //! sources that are enabled can be reflected to the processor interrupt. //! Disabled sources have no effect on the processor. //! -//! \param intFlags is the bitwise OR of the interrupt sources to be enabled. +//! \param [in] intFlags is the bitwise OR of the interrupt sources to be enabled. //! - \ref AES_DMA_IN_DONE //! - \ref AES_RESULT_RDY //! @@ -630,7 +692,7 @@ __STATIC_INLINE uint32_t AESIntStatusRaw(void) //! clear the event source early in the interrupt service routine (ISR) to allow //! the event clear to propagate to the NVIC before returning from the ISR. //! -//! \param intFlags is a bit mask of the interrupt sources to be cleared. +//! \param [in] intFlags is a bit mask of the interrupt sources to be cleared. //! - \ref AES_DMA_IN_DONE //! - \ref AES_RESULT_RDY //! @@ -714,14 +776,22 @@ __STATIC_INLINE void AESIntUnregister(void) #undef AESStartDMAOperation #define AESStartDMAOperation ROM_AESStartDMAOperation #endif - #ifdef ROM_AESLoadInitializationVector - #undef AESLoadInitializationVector - #define AESLoadInitializationVector ROM_AESLoadInitializationVector + #ifdef ROM_AESSetInitializationVector + #undef AESSetInitializationVector + #define AESSetInitializationVector ROM_AESSetInitializationVector + #endif + #ifdef ROM_AESWriteCCMInitializationVector + #undef AESWriteCCMInitializationVector + #define AESWriteCCMInitializationVector ROM_AESWriteCCMInitializationVector #endif #ifdef ROM_AESReadTag #undef AESReadTag #define AESReadTag ROM_AESReadTag #endif + #ifdef ROM_AESVerifyTag + #undef AESVerifyTag + #define AESVerifyTag ROM_AESVerifyTag + #endif #ifdef ROM_AESWriteToKeyStore #undef AESWriteToKeyStore #define AESWriteToKeyStore ROM_AESWriteToKeyStore @@ -734,6 +804,10 @@ __STATIC_INLINE void AESIntUnregister(void) #undef AESWaitForIRQFlags #define AESWaitForIRQFlags ROM_AESWaitForIRQFlags #endif + #ifdef ROM_AESConfigureCCMCtrl + #undef AESConfigureCCMCtrl + #define AESConfigureCCMCtrl ROM_AESConfigureCCMCtrl + #endif #endif //***************************************************************************** diff --git a/third_party/ti/devices/cc26x2/driverlib/aes_doc.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aes_doc.h similarity index 97% rename from third_party/ti/devices/cc26x2/driverlib/aes_doc.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aes_doc.h index 502f95431..6d156a4ab 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aes_doc.h +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aes_doc.h @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aes_doc.h -* Revised: 2016-12-10 13:57:16 +0100 (Sat, 10 Dec 2016) -* Revision: 47952 +* Revised: 2017-06-05 12:13:49 +0200 (Mon, 05 Jun 2017) +* Revision: 49096 * * Copyright (c) 2015 - 2017, Texas Instruments Incorporated * All rights reserved. diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_batmon.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_batmon.c similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/aon_batmon.c rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_batmon.c diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_batmon.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_batmon.h similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/aon_batmon.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_batmon.h diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_event.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_event.c similarity index 98% rename from third_party/ti/devices/cc26x2/driverlib/aon_event.c rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_event.c index c94e9bfbc..cb699a152 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aon_event.c +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_event.c @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aon_event.c -* Revised: 2017-04-26 16:53:03 +0200 (Wed, 26 Apr 2017) -* Revision: 48850 +* Revised: 2017-06-05 12:13:49 +0200 (Mon, 05 Jun 2017) +* Revision: 49096 * * Description: Driver for the AON Event fabric. * diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_event.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_event.h similarity index 99% rename from third_party/ti/devices/cc26x2/driverlib/aon_event.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_event.h index 7bd2ca623..999844a0d 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aon_event.h +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_event.h @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aon_event.h -* Revised: 2017-04-26 16:53:03 +0200 (Wed, 26 Apr 2017) -* Revision: 48850 +* Revised: 2017-08-09 16:56:05 +0200 (Wed, 09 Aug 2017) +* Revision: 49506 * * Description: Defines and prototypes for the AON Event fabric. * @@ -63,7 +63,6 @@ extern "C" #include #include "../inc/hw_types.h" #include "../inc/hw_memmap.h" -#include "../inc/hw_device.h" #include "../inc/hw_aon_event.h" #include "debug.h" @@ -168,11 +167,10 @@ extern "C" // //! \brief Select event source for the specified MCU wake-up programmable event. //! -//! The AON event fabric has several programmable events that can -//! wake up the MCU. The events are forwarded to the wake-up controller (WUC). +//! The AON event fabric has several programmable events that can wake up the MCU. //! //! \note The programmable event sources are effectively OR'ed together -//! to form a single wake-up event forwarded to the WUC. +//! to form a single wake-up event. //! //! \param ui32MCUWUEvent is one of the programmable MCU wake-up event sources. //! - \ref AON_EVENT_MCU_WU0 diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_event_doc.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_event_doc.h similarity index 83% rename from third_party/ti/devices/cc26x2/driverlib/aon_event_doc.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_event_doc.h index 96dc5b57a..5210bbfc7 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aon_event_doc.h +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_event_doc.h @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aon_event_doc.h -* Revised: 2016-07-07 19:12:02 +0200 (Thu, 07 Jul 2016) -* Revision: 46848 +* Revised: 2017-08-09 16:56:05 +0200 (Wed, 09 Aug 2017) +* Revision: 49506 * * Copyright (c) 2015 - 2017, Texas Instruments Incorporated * All rights reserved. @@ -42,11 +42,10 @@ //! to the AON event fabric. For more information on MCU event fabric, see [MCU event API](@ref event_api). //! //! The AON event fabric is a configurable combinatorial router between AON event sources and event -//! subscribers in both AON and MCU domains. The AON event fabric has three main event subscribers: AON WUC, -//! AON RTC, and MCU event fabric. The API to control the AON event fabric configuration can be grouped based -//! on the event subscriber to configure: +//! subscribers in both AON and MCU domains. The API to control the AON event fabric configuration +//! can be grouped based on the event subscriber to configure: //! -//! - AON WUC receives two programmable event lines from AON event fabric. One for MCU wake-up events and one for AUX wake-up events. For more information, see [AON WUC API](@ref aonwuc_api). +//! - Wake-up events. //! - MCU wake-up event //! - @ref AONEventMcuWakeUpSet() //! - @ref AONEventMcuWakeUpGet() diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_ioc.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_ioc.c similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/aon_ioc.c rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_ioc.c diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_ioc.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_ioc.h similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/aon_ioc.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_ioc.h diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_ioc_doc.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_ioc_doc.h similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/aon_ioc_doc.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_ioc_doc.h diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_pmctl.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_pmctl.c similarity index 95% rename from third_party/ti/devices/cc26x2/driverlib/aon_pmctl.c rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_pmctl.c index 771db904a..b680fd73e 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aon_pmctl.c +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_pmctl.c @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aon_pmctl.c -* Revised: 2017-03-28 11:12:40 +0200 (Tue, 28 Mar 2017) -* Revision: 48729 +* Revised: 2017-06-05 12:13:49 +0200 (Mon, 05 Jun 2017) +* Revision: 49096 * * Description: Driver for the AON Power-Management Controller. * diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_pmctl.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_pmctl.h similarity index 86% rename from third_party/ti/devices/cc26x2/driverlib/aon_pmctl.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_pmctl.h index f1123d63b..ec6bf2e53 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aon_pmctl.h +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_pmctl.h @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aon_pmctl.h -* Revised: 2017-04-20 13:30:18 +0200 (Thu, 20 Apr 2017) -* Revision: 48814 +* Revised: 2017-11-02 14:16:14 +0100 (Thu, 02 Nov 2017) +* Revision: 50156 * * Description: Defines and prototypes for the AON Power-Management Controller * @@ -127,11 +127,11 @@ AONPMCTLMcuSRamRetConfig(uint32_t ui32Retention) uint32_t ui32Reg; // Check the arguments. - ASSERT(ui32Retention == MCU_RAM_RET_NONE || - ui32Retention == MCU_RAM_RET_LVL1 || - ui32Retention == MCU_RAM_RET_LVL2 || - ui32Retention == MCU_RAM_RET_LVL3 || - ui32Retention == MCU_RAM_RET_FULL); + ASSERT((ui32Retention == MCU_RAM_RET_NONE) || + (ui32Retention == MCU_RAM_RET_LVL1) || + (ui32Retention == MCU_RAM_RET_LVL2) || + (ui32Retention == MCU_RAM_RET_LVL3) || + (ui32Retention == MCU_RAM_RET_FULL)); // Configure the retention. ui32Reg = HWREG(AON_PMCTL_BASE + AON_PMCTL_O_RAMCFG) & ~AON_PMCTL_RAMCFG_BUS_SRAM_RET_EN_M; @@ -157,27 +157,6 @@ AONPMCTLPowerStatusGet(void) return (HWREG(AON_PMCTL_BASE + AON_PMCTL_O_PWRSTAT)); } -//***************************************************************************** -// -//! \brief Enable shut-down of the device. -//! -//! Use this function to enable shut-down of the device. This will force all I/O -//! values to be latched - possibly enabling I/O wakeup - then all internal power -//! supplies are turned off, effectively putting the device into shut-down mode. -//! -//! -//! \return None -// -//***************************************************************************** -__STATIC_INLINE void -AONPMCTLShutDownEnable(void) -{ - // Power down the JTAG domain - HWREGBITW(AON_PMCTL_BASE + AON_PMCTL_O_PWRSTAT, AON_PMCTL_PWRSTAT_JTAG_PD_ON_BITN) = 0; - // Enable shutdown of the device - HWREGBITW(AON_PMCTL_BASE + AON_PMCTL_O_SHUTDOWN, AON_PMCTL_SHUTDOWN_EN_BITN) = 1; -} - //***************************************************************************** // diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_pmctl_doc.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_pmctl_doc.h similarity index 95% rename from third_party/ti/devices/cc26x2/driverlib/aon_pmctl_doc.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_pmctl_doc.h index 5347a990a..0f44256b2 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aon_pmctl_doc.h +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_pmctl_doc.h @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aon_pmctl_doc.h -* Revised: 2017-03-28 11:12:40 +0200 (Tue, 28 Mar 2017) -* Revision: 48729 +* Revised: 2017-11-02 15:41:14 +0100 (Thu, 02 Nov 2017) +* Revision: 50165 * * Copyright (c) 2015 - 2017, Texas Instruments Incorporated * All rights reserved. @@ -83,13 +83,10 @@ //! Functions to perform device configuration: //! - \ref AONPMCTLJtagPowerOff() //! - \ref AONPMCTLMcuSRamRetConfig() -//! - \ref AONPMCTLShutDownEnable() //! //! Please note that due to legacy software compatibility some functionalities controlled //! by the AON Power Management Controller module are supported through the APIs of //! the [System Controller](@ref sysctrl_api) and [Power Controller](@ref pwrctrl_api). Relevant functions are: -//! - \ref PowerCtrlIOFreezeDisable() -//! - \ref PowerCtrlIOFreezeEnable() //! - \ref PowerCtrlSourceGet() //! - \ref PowerCtrlSourceSet() //! - \ref PowerCtrlResetSourceGet() diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_rtc.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_rtc.c similarity index 97% rename from third_party/ti/devices/cc26x2/driverlib/aon_rtc.c rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_rtc.c index 21a45a54e..7187f84de 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aon_rtc.c +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_rtc.c @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aon_rtc.c -* Revised: 2016-10-06 17:21:09 +0200 (Thu, 06 Oct 2016) -* Revision: 47343 +* Revised: 2017-06-05 12:13:49 +0200 (Mon, 05 Jun 2017) +* Revision: 49096 * * Description: Driver for the AON RTC. * diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_rtc.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_rtc.h similarity index 99% rename from third_party/ti/devices/cc26x2/driverlib/aon_rtc.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_rtc.h index 2a6270dbf..6e131d2f3 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aon_rtc.h +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_rtc.h @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aon_rtc.h -* Revised: 2016-10-06 17:21:09 +0200 (Thu, 06 Oct 2016) -* Revision: 47343 +* Revised: 2017-08-16 15:13:43 +0200 (Wed, 16 Aug 2017) +* Revision: 49593 * * Description: Defines and prototypes for the AON RTC * diff --git a/third_party/ti/devices/cc26x2/driverlib/aon_rtc_doc.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_rtc_doc.h similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/aon_rtc_doc.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aon_rtc_doc.h diff --git a/third_party/ti/devices/cc26x2/driverlib/aux_adc.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_adc.c similarity index 97% rename from third_party/ti/devices/cc26x2/driverlib/aux_adc.c rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_adc.c index 2e946484b..b1b3f198f 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aux_adc.c +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_adc.c @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aux_adc.c -* Revised: 2017-04-26 18:27:45 +0200 (Wed, 26 Apr 2017) -* Revision: 48852 +* Revised: 2017-11-20 14:31:35 +0100 (Mon, 20 Nov 2017) +* Revision: 50315 * * Description: Driver for the AUX Time to Digital Converter interface. * @@ -95,6 +95,10 @@ AUXADCDisable(void) // Ensure that scaling is enabled by default before next use of the ADC ADI8BitsClear(AUX_ADI4_BASE, ADI_4_AUX_O_ADC1, ADI_4_AUX_ADC1_SCALE_DIS_M); + // Flush the FIFO before disabling the clocks + HWREGBITW(AUX_ANAIF_BASE + AUX_ANAIF_O_ADCCTL, 1) = 1; // CMD: EN(1) -> FLUSH(3) + HWREGBITW(AUX_ANAIF_BASE + AUX_ANAIF_O_ADCCTL, 1) = 0; // CMD: FLUSH(3) -> EN(1) + // Disable the ADC clock (no need to wait since IOB_WUC_ADCCLKCTL_ACK goes low immediately) HWREG(AUX_SYSIF_BASE + AUX_SYSIF_O_ADCCLKCTL) = 0; diff --git a/third_party/ti/devices/cc26x2/driverlib/aux_adc.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_adc.h similarity index 96% rename from third_party/ti/devices/cc26x2/driverlib/aux_adc.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_adc.h index 69d271403..c87fd2fb9 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aux_adc.h +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_adc.h @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aux_adc.h -* Revised: 2016-09-19 10:36:17 +0200 (Mon, 19 Sep 2016) -* Revision: 47179 +* Revised: 2018-02-07 09:45:39 +0100 (Wed, 07 Feb 2018) +* Revision: 51437 * * Description: Defines and prototypes for the AUX Analog-to-Digital * Converter @@ -132,6 +132,15 @@ extern "C" #define AUXADC_TRIGGER_GPT2B (EVENT_AUXSEL0_EV_GPT2B) #define AUXADC_TRIGGER_GPT3A (EVENT_AUXSEL0_EV_GPT3A) #define AUXADC_TRIGGER_GPT3B (EVENT_AUXSEL0_EV_GPT3B) +// Additional triggers specific for cc26x2 and cc13x2 devices +#define AUXADC_TRIGGER_GPT0A_CMP (EVENT_AUXSEL0_EV_GPT0A_CMP) +#define AUXADC_TRIGGER_GPT0B_CMP (EVENT_AUXSEL0_EV_GPT0B_CMP) +#define AUXADC_TRIGGER_GPT1A_CMP (EVENT_AUXSEL0_EV_GPT1A_CMP) +#define AUXADC_TRIGGER_GPT1B_CMP (EVENT_AUXSEL0_EV_GPT1B_CMP) +#define AUXADC_TRIGGER_GPT2A_CMP (EVENT_AUXSEL0_EV_GPT2A_CMP) +#define AUXADC_TRIGGER_GPT2B_CMP (EVENT_AUXSEL0_EV_GPT2B_CMP) +#define AUXADC_TRIGGER_GPT3A_CMP (EVENT_AUXSEL0_EV_GPT3A_CMP) +#define AUXADC_TRIGGER_GPT3B_CMP (EVENT_AUXSEL0_EV_GPT3B_CMP) //***************************************************************************** // diff --git a/third_party/ti/devices/cc26x2/driverlib/aux_smph.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_smph.c similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/aux_smph.c rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_smph.c diff --git a/third_party/ti/devices/cc26x2/driverlib/aux_smph.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_smph.h similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/aux_smph.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_smph.h diff --git a/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_sysif.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_sysif.c new file mode 100644 index 000000000..5e3e90b7c --- /dev/null +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_sysif.c @@ -0,0 +1,96 @@ +/****************************************************************************** +* Filename: aux_sysif.c +* Revised: 2018-04-17 14:54:06 +0200 (Tue, 17 Apr 2018) +* Revision: 51890 +* +* Description: Driver for the AUX System Interface +* +* Copyright (c) 2015 - 2017, Texas Instruments Incorporated +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1) Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2) Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3) Neither the name of the ORGANIZATION nor the names of its contributors may +* be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, 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 "aux_sysif.h" + +//***************************************************************************** +// +// Handle support for DriverLib in ROM: +// This section will undo prototype renaming made in the header file +// +//***************************************************************************** +#if !defined(DOXYGEN) + #undef AUXSYSIFOpModeChange + #define AUXSYSIFOpModeChange NOROM_AUXSYSIFOpModeChange +#endif + + +//***************************************************************************** +// +// Used in AUXSYSIFOpModeChange() to control the change of the operational mode. +// +//***************************************************************************** +static const uint8_t g_OpMode_to_order[4] = {1,2,0,3}; +static const uint8_t g_Order_to_OpMode[4] = {2,0,1,3}; + +//***************************************************************************** +// +// Controls AUX operational mode change +// +//***************************************************************************** +void +AUXSYSIFOpModeChange(uint32_t targetOpMode) +{ + uint32_t currentOpMode; + uint32_t currentOrder; + uint32_t nextMode; + + // Check the argument + ASSERT((targetOpMode == AUX_SYSIF_OPMODEREQ_REQ_PDLP)|| + (targetOpMode == AUX_SYSIF_OPMODEREQ_REQ_PDA) || + (targetOpMode == AUX_SYSIF_OPMODEREQ_REQ_LP) || + (targetOpMode == AUX_SYSIF_OPMODEREQ_REQ_A)); + + do { + currentOpMode = HWREG(AUX_SYSIF_BASE + AUX_SYSIF_O_OPMODEREQ); + while ( currentOpMode != HWREG(AUX_SYSIF_BASE + AUX_SYSIF_O_OPMODEACK)); + if (currentOpMode != targetOpMode) + { + currentOrder = g_OpMode_to_order[currentOpMode]; + if ( currentOrder < g_OpMode_to_order[targetOpMode]) + { + nextMode = g_Order_to_OpMode[currentOrder + 1]; + } + else + { + nextMode = g_Order_to_OpMode[currentOrder - 1]; + } + HWREG(AUX_SYSIF_BASE + AUX_SYSIF_O_OPMODEREQ) = nextMode; + } + } while ( currentOpMode != targetOpMode ); +} diff --git a/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_sysif.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_sysif.h new file mode 100644 index 000000000..04214bc1a --- /dev/null +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_sysif.h @@ -0,0 +1,154 @@ +/****************************************************************************** +* Filename: aux_sysif.h +* Revised: 2017-06-27 08:41:49 +0200 (Tue, 27 Jun 2017) +* Revision: 49245 +* +* Description: Defines and prototypes for the AUX System Interface +* +* Copyright (c) 2015 - 2017, Texas Instruments Incorporated +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1) Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2) Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3) Neither the name of the ORGANIZATION nor the names of its contributors may +* be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. +* +******************************************************************************/ + +//***************************************************************************** +// +//! \addtogroup aux_group +//! @{ +//! \addtogroup auxsysif_api +//! @{ +// +//***************************************************************************** + +#ifndef __AUX_SYSIF_H__ +#define __AUX_SYSIF_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include "../inc/hw_types.h" +#include "../inc/hw_memmap.h" +#include "../inc/hw_aux_sysif.h" +#include "debug.h" + +//***************************************************************************** +// +// Support for DriverLib in ROM: +// This section renames all functions that are not "static inline", so that +// calling these functions will default to implementation in flash. At the end +// of this file a second renaming will change the defaults to implementation in +// ROM for available functions. +// +// To force use of the implementation in flash, e.g. for debugging: +// - Globally: Define DRIVERLIB_NOROM at project level +// - Per function: Use prefix "NOROM_" when calling the function +// +//***************************************************************************** +#if !defined(DOXYGEN) + #define AUXSYSIFOpModeChange NOROM_AUXSYSIFOpModeChange +#endif + + +//***************************************************************************** +// +// API Functions and prototypes +// +//***************************************************************************** + +//***************************************************************************** +// +// Defines for AUX operational modes. +// +//***************************************************************************** +#define AUX_SYSIF_OPMODE_TARGET_PDLP (AUX_SYSIF_OPMODEREQ_REQ_PDLP) +#define AUX_SYSIF_OPMODE_TARGET_PDA (AUX_SYSIF_OPMODEREQ_REQ_PDA) +#define AUX_SYSIF_OPMODE_TARGET_LP (AUX_SYSIF_OPMODEREQ_REQ_LP) +#define AUX_SYSIF_OPMODE_TARGET_A (AUX_SYSIF_OPMODEREQ_REQ_A) + +//***************************************************************************** +// +//! \brief Changes the AUX operational mode to the requested target mode. +//! +//! This function controls the change of the AUX operational mode. +//! The function controls the change of the current operational mode to the +//! operational mode target by adhering to rules specified by HW. +//! +//! \param targetOpMode +//! AUX operational mode: +//! - \ref AUX_SYSIF_OPMODE_TARGET_PDLP (Powerdown operational mode with wakeup to lowpower mode) +//! - \ref AUX_SYSIF_OPMODE_TARGET_PDA (Powerdown operational mode with wakeup to active mode) +//! - \ref AUX_SYSIF_OPMODE_TARGET_LP (Lowpower operational mode) +//! - \ref AUX_SYSIF_OPMODE_TARGET_A (Active operational mode) +//! +//! \return None +// +//***************************************************************************** +extern void AUXSYSIFOpModeChange(uint32_t targetOpMode); + +//***************************************************************************** +// +// Support for DriverLib in ROM: +// Redirect to implementation in ROM when available. +// +//***************************************************************************** +#if !defined(DRIVERLIB_NOROM) && !defined(DOXYGEN) + #include "../driverlib/rom.h" + #ifdef ROM_AUXSYSIFOpModeChange + #undef AUXSYSIFOpModeChange + #define AUXSYSIFOpModeChange ROM_AUXSYSIFOpModeChange + #endif +#endif + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __AUX_SYSIF_H__ + +//***************************************************************************** +// +//! Close the Doxygen group. +//! @} +//! @} +// +//***************************************************************************** diff --git a/third_party/ti/devices/cc26x2/driverlib/aux_tdc.c b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_tdc.c similarity index 100% rename from third_party/ti/devices/cc26x2/driverlib/aux_tdc.c rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_tdc.c diff --git a/third_party/ti/devices/cc26x2/driverlib/aux_tdc.h b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_tdc.h similarity index 78% rename from third_party/ti/devices/cc26x2/driverlib/aux_tdc.h rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_tdc.h index 7c869b116..402c83423 100644 --- a/third_party/ti/devices/cc26x2/driverlib/aux_tdc.h +++ b/third_party/ti/devices/cc13x2_cc26x2/driverlib/aux_tdc.h @@ -1,7 +1,7 @@ /****************************************************************************** * Filename: aux_tdc.h -* Revised: 2017-03-28 11:12:40 +0200 (Tue, 28 Mar 2017) -* Revision: 48729 +* Revised: 2017-06-05 12:13:49 +0200 (Mon, 05 Jun 2017) +* Revision: 49096 * * Description: Defines and prototypes for the AUX Time-to-Digital Converter * @@ -128,19 +128,6 @@ extern "C" #define AUXTDC_STOPPOL_RIS (AUX_TDC_TRIGSRC_STOP_POL_HIGH) // Rising edge polarity for stop event #define AUXTDC_STOPPOL_FALL (AUX_TDC_TRIGSRC_STOP_POL_LOW) // Falling edge polarity for stop event -#define AUXTDC_STOP_AON_RTC_CH2 (AUX_TDC_TRIGSRC_STOP_SRC_AON_RTC_CH2) -#define AUXTDC_STOP_AUX_COMPA (AUX_TDC_TRIGSRC_STOP_SRC_AUX_COMPA) -#define AUXTDC_STOP_AUX_COMPB (AUX_TDC_TRIGSRC_STOP_SRC_AUX_COMPB) -#define AUXTDC_STOP_ISRC_RESET (AUX_TDC_TRIGSRC_STOP_SRC_ISRC_RESET) -#define AUXTDC_STOP_TIMER0_EV (AUX_TDC_TRIGSRC_STOP_SRC_TIMER0_EV) -#define AUXTDC_STOP_TIMER1_EV (AUX_TDC_TRIGSRC_STOP_SRC_TIMER1_EV) -#define AUXTDC_STOP_SMPH_AUTOTAKE_DONE (AUX_TDC_TRIGSRC_STOP_SRC_SMPH_AUTOTAKE_DONE) -#define AUXTDC_STOP_ADC_DONE (AUX_TDC_TRIGSRC_STOP_SRC_ADC_DONE) -#define AUXTDC_STOP_ADC_FIFO_ALMOST_FULL (AUX_TDC_TRIGSRC_STOP_SRC_ADC_FIFO_ALMOST_FULL) -#define AUXTDC_STOP_OBSMUX0 (AUX_TDC_TRIGSRC_STOP_SRC_OBSMUX0) -#define AUXTDC_STOP_OBSMUX1 (AUX_TDC_TRIGSRC_STOP_SRC_OBSMUX1) -#define AUXTDC_STOP_AON_SW (AUX_TDC_TRIGSRC_STOP_SRC_AON_SW) -#define AUXTDC_STOP_AON_PROG_WU (AUX_TDC_TRIGSRC_STOP_SRC_AON_PROG_WU) #define AUXTDC_STOP_AUXIO0 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO0) #define AUXTDC_STOP_AUXIO1 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO1) #define AUXTDC_STOP_AUXIO2 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO2) @@ -157,26 +144,58 @@ extern "C" #define AUXTDC_STOP_AUXIO13 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO13) #define AUXTDC_STOP_AUXIO14 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO14) #define AUXTDC_STOP_AUXIO15 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO15) +#define AUXTDC_STOP_AUXIO16 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO16) +#define AUXTDC_STOP_AUXIO17 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO17) +#define AUXTDC_STOP_AUXIO18 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO18) +#define AUXTDC_STOP_AUXIO19 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO19) +#define AUXTDC_STOP_AUXIO20 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO20) +#define AUXTDC_STOP_AUXIO21 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO21) +#define AUXTDC_STOP_AUXIO22 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO22) +#define AUXTDC_STOP_AUXIO23 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO23) +#define AUXTDC_STOP_AUXIO24 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO24) +#define AUXTDC_STOP_AUXIO25 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO25) +#define AUXTDC_STOP_AUXIO26 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO26) +#define AUXTDC_STOP_AUXIO27 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO27) +#define AUXTDC_STOP_AUXIO28 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO28) +#define AUXTDC_STOP_AUXIO29 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO29) +#define AUXTDC_STOP_AUXIO30 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO30) +#define AUXTDC_STOP_AUXIO31 (AUX_TDC_TRIGSRC_STOP_SRC_AUXIO31) +#define AUXTDC_STOP_MANUAL_EV (AUX_TDC_TRIGSRC_STOP_SRC_MANUAL_EV) +#define AUXTDC_STOP_AON_RTC_CH2_DLY (AUX_TDC_TRIGSRC_STOP_SRC_AON_RTC_CH2_DLY) +#define AUXTDC_STOP_AON_RTC_4KHZ (AUX_TDC_TRIGSRC_STOP_SRC_AON_RTC_4KHZ) +#define AUXTDC_STOP_AON_BATMON_BAT_UPD (AUX_TDC_TRIGSRC_STOP_SRC_AON_BATMON_BAT_UPD) +#define AUXTDC_STOP_AON_BATMON_TEMP_UPD (AUX_TDC_TRIGSRC_STOP_SRC_AON_BATMON_TEMP_UPD) +#define AUXTDC_STOP_SCLK_LF (AUX_TDC_TRIGSRC_STOP_SRC_SCLK_LF) +#define AUXTDC_STOP_PWR_DWN (AUX_TDC_TRIGSRC_STOP_SRC_PWR_DWN) +#define AUXTDC_STOP_MCU_ACTIVE (AUX_TDC_TRIGSRC_STOP_SRC_MCU_ACTIVE) +#define AUXTDC_STOP_VDDR_RECHARGE (AUX_TDC_TRIGSRC_STOP_SRC_VDDR_RECHARGE) +#define AUXTDC_STOP_TIMER2_EV0 (AUX_TDC_TRIGSRC_STOP_SRC_AUX_TIMER2_EV0) +#define AUXTDC_STOP_TIMER2_EV1 (AUX_TDC_TRIGSRC_STOP_SRC_AUX_TIMER2_EV1) +#define AUXTDC_STOP_TIMER2_EV2 (AUX_TDC_TRIGSRC_STOP_SRC_AUX_TIMER2_EV2) +#define AUXTDC_STOP_TIMER2_EV3 (AUX_TDC_TRIGSRC_STOP_SRC_AUX_TIMER2_EV3) +#define AUXTDC_STOP_TIMER2_PULSE (AUX_TDC_TRIGSRC_STOP_SRC_AUX_TIMER2_PULSE) +#define AUXTDC_STOP_TDC_DONE (AUX_TDC_TRIGSRC_STOP_SRC_AUX_TDC_DONE) +#define AUXTDC_STOP_ADC_IRQ (AUX_TDC_TRIGSRC_STOP_SRC_AUX_ADC_IRQ) +#define AUXTDC_STOP_ADC_FIFO_NOT_EMPTY (AUX_TDC_TRIGSRC_STOP_SRC_AUX_ADC_FIFO_NOT_EMPTY) +#define AUXTDC_STOP_NO_EVENT (AUX_TDC_TRIGSRC_STOP_SRC_NO_EVENT) +#define AUXTDC_STOP_ADC_DONE (AUX_TDC_TRIGSRC_STOP_SRC_AUX_ADC_DONE) +#define AUXTDC_STOP_ADC_FIFO_ALMOST_FULL (AUX_TDC_TRIGSRC_STOP_SRC_AUX_ADC_FIFO_ALMOST_FULL) +#define AUXTDC_STOP_ISRC_RESET (AUX_TDC_TRIGSRC_STOP_SRC_AUX_ISRC_RESET_N) +#define AUXTDC_STOP_OBSMUX0 (AUX_TDC_TRIGSRC_STOP_SRC_MCU_OBSMUX0) +#define AUXTDC_STOP_OBSMUX1 (AUX_TDC_TRIGSRC_STOP_SRC_MCU_OBSMUX1) +#define AUXTDC_STOP_SMPH_AUTOTAKE_DONE (AUX_TDC_TRIGSRC_STOP_SRC_AUX_SMPH_AUTOTAKE_DONE) +#define AUXTDC_STOP_TDC_PRE (AUX_TDC_TRIGSRC_STOP_SRC_AUX_TDC_PRE) +#define AUXTDC_STOP_TIMER0_EV (AUX_TDC_TRIGSRC_STOP_SRC_AUX_TIMER0_EV) +#define AUXTDC_STOP_TIMER1_EV (AUX_TDC_TRIGSRC_STOP_SRC_AUX_TIMER1_EV) +#define AUXTDC_STOP_AON_RTC_CH2 (AUX_TDC_TRIGSRC_STOP_SRC_AON_RTC_CH2) +#define AUXTDC_STOP_AUX_COMPA (AUX_TDC_TRIGSRC_STOP_SRC_AUX_COMPA) +#define AUXTDC_STOP_AUX_COMPB (AUX_TDC_TRIGSRC_STOP_SRC_AUX_COMPB) #define AUXTDC_STOP_ACLK_REF (AUX_TDC_TRIGSRC_STOP_SRC_ACLK_REF) #define AUXTDC_STOP_MCU_EV (AUX_TDC_TRIGSRC_STOP_SRC_MCU_EV) -#define AUXTDC_STOP_TDC_PRE (AUX_TDC_TRIGSRC_STOP_SRC_TDC_PRE) #define AUXTDC_STARTPOL_RIS (AUX_TDC_TRIGSRC_START_POL_HIGH) // Rising edge polarity for start event #define AUXTDC_STARTPOL_FALL (AUX_TDC_TRIGSRC_START_POL_LOW) // Falling edge polarity for start event -#define AUXTDC_START_AON_RTC_CH2 (AUX_TDC_TRIGSRC_START_SRC_AON_RTC_CH2) -#define AUXTDC_START_AUX_COMPA (AUX_TDC_TRIGSRC_START_SRC_AUX_COMPA) -#define AUXTDC_START_AUX_COMPB (AUX_TDC_TRIGSRC_START_SRC_AUX_COMPB) -#define AUXTDC_START_ISRC_RESET (AUX_TDC_TRIGSRC_START_SRC_ISRC_RESET) -#define AUXTDC_START_TIMER0_EV (AUX_TDC_TRIGSRC_START_SRC_TIMER0_EV) -#define AUXTDC_START_TIMER1_EV (AUX_TDC_TRIGSRC_START_SRC_TIMER1_EV) -#define AUXTDC_START_SMPH_AUTOTAKE_DONE (AUX_TDC_TRIGSRC_START_SRC_SMPH_AUTOTAKE_DONE) -#define AUXTDC_START_ADC_DONE (AUX_TDC_TRIGSRC_START_SRC_ADC_DONE) -#define AUXTDC_START_ADC_FIFO_ALMOST_FULL (AUX_TDC_TRIGSRC_START_SRC_ADC_FIFO_ALMOST_FULL) -#define AUXTDC_START_OBSMUX0 (AUX_TDC_TRIGSRC_START_SRC_OBSMUX0) -#define AUXTDC_START_OBSMUX1 (AUX_TDC_TRIGSRC_START_SRC_OBSMUX1) -#define AUXTDC_START_AON_SW (AUX_TDC_TRIGSRC_START_SRC_AON_SW) -#define AUXTDC_START_AON_PROG_WU (AUX_TDC_TRIGSRC_START_SRC_AON_PROG_WU) #define AUXTDC_START_AUXIO0 (AUX_TDC_TRIGSRC_START_SRC_AUXIO0) #define AUXTDC_START_AUXIO1 (AUX_TDC_TRIGSRC_START_SRC_AUXIO1) #define AUXTDC_START_AUXIO2 (AUX_TDC_TRIGSRC_START_SRC_AUXIO2) @@ -193,9 +212,54 @@ extern "C" #define AUXTDC_START_AUXIO13 (AUX_TDC_TRIGSRC_START_SRC_AUXIO13) #define AUXTDC_START_AUXIO14 (AUX_TDC_TRIGSRC_START_SRC_AUXIO14) #define AUXTDC_START_AUXIO15 (AUX_TDC_TRIGSRC_START_SRC_AUXIO15) +#define AUXTDC_START_AUXIO16 (AUX_TDC_TRIGSRC_START_SRC_AUXIO16) +#define AUXTDC_START_AUXIO17 (AUX_TDC_TRIGSRC_START_SRC_AUXIO17) +#define AUXTDC_START_AUXIO18 (AUX_TDC_TRIGSRC_START_SRC_AUXIO18) +#define AUXTDC_START_AUXIO19 (AUX_TDC_TRIGSRC_START_SRC_AUXIO19) +#define AUXTDC_START_AUXIO20 (AUX_TDC_TRIGSRC_START_SRC_AUXIO20) +#define AUXTDC_START_AUXIO21 (AUX_TDC_TRIGSRC_START_SRC_AUXIO21) +#define AUXTDC_START_AUXIO22 (AUX_TDC_TRIGSRC_START_SRC_AUXIO22) +#define AUXTDC_START_AUXIO23 (AUX_TDC_TRIGSRC_START_SRC_AUXIO23) +#define AUXTDC_START_AUXIO24 (AUX_TDC_TRIGSRC_START_SRC_AUXIO24) +#define AUXTDC_START_AUXIO25 (AUX_TDC_TRIGSRC_START_SRC_AUXIO25) +#define AUXTDC_START_AUXIO26 (AUX_TDC_TRIGSRC_START_SRC_AUXIO26) +#define AUXTDC_START_AUXIO27 (AUX_TDC_TRIGSRC_START_SRC_AUXIO27) +#define AUXTDC_START_AUXIO28 (AUX_TDC_TRIGSRC_START_SRC_AUXIO28) +#define AUXTDC_START_AUXIO29 (AUX_TDC_TRIGSRC_START_SRC_AUXIO29) +#define AUXTDC_START_AUXIO30 (AUX_TDC_TRIGSRC_START_SRC_AUXIO30) +#define AUXTDC_START_AUXIO31 (AUX_TDC_TRIGSRC_START_SRC_AUXIO31) +#define AUXTDC_START_MANUAL_EV (AUX_TDC_TRIGSRC_START_SRC_MANUAL_EV) +#define AUXTDC_START_AON_RTC_CH2_DLY (AUX_TDC_TRIGSRC_START_SRC_AON_RTC_CH2_DLY) +#define AUXTDC_START_AON_RTC_4KHZ (AUX_TDC_TRIGSRC_START_SRC_AON_RTC_4KHZ) +#define AUXTDC_START_AON_BATMON_BAT_UPD (AUX_TDC_TRIGSRC_START_SRC_AON_BATMON_BAT_UPD) +#define AUXTDC_START_AON_BATMON_TEMP_UPD (AUX_TDC_TRIGSRC_START_SRC_AON_BATMON_TEMP_UPD) +#define AUXTDC_START_SCLK_LF (AUX_TDC_TRIGSRC_START_SRC_SCLK_LF) +#define AUXTDC_START_PWR_DWN (AUX_TDC_TRIGSRC_START_SRC_PWR_DWN) +#define AUXTDC_START_MCU_ACTIVE (AUX_TDC_TRIGSRC_START_SRC_MCU_ACTIVE) +#define AUXTDC_START_VDDR_RECHARGE (AUX_TDC_TRIGSRC_START_SRC_VDDR_RECHARGE) +#define AUXTDC_START_TIMER2_EV0 (AUX_TDC_TRIGSRC_START_SRC_AUX_TIMER2_EV0) +#define AUXTDC_START_TIMER2_EV1 (AUX_TDC_TRIGSRC_START_SRC_AUX_TIMER2_EV1) +#define AUXTDC_START_TIMER2_EV2 (AUX_TDC_TRIGSRC_START_SRC_AUX_TIMER2_EV2) +#define AUXTDC_START_TIMER2_EV3 (AUX_TDC_TRIGSRC_START_SRC_AUX_TIMER2_EV3) +#define AUXTDC_START_TIMER2_PULSE (AUX_TDC_TRIGSRC_START_SRC_AUX_TIMER2_PULSE) +#define AUXTDC_START_TDC_DONE (AUX_TDC_TRIGSRC_START_SRC_AUX_TDC_DONE) +#define AUXTDC_START_ADC_IRQ (AUX_TDC_TRIGSRC_START_SRC_AUX_ADC_IRQ) +#define AUXTDC_START_ADC_FIFO_NOT_EMPTY (AUX_TDC_TRIGSRC_START_SRC_AUX_ADC_FIFO_NOT_EMPTY) +#define AUXTDC_START_NO_EVENT (AUX_TDC_TRIGSRC_START_SRC_NO_EVENT) +#define AUXTDC_START_ADC_DONE (AUX_TDC_TRIGSRC_START_SRC_AUX_ADC_DONE) +#define AUXTDC_START_ADC_FIFO_ALMOST_FULL (AUX_TDC_TRIGSRC_START_SRC_AUX_ADC_FIFO_ALMOST_FULL) +#define AUXTDC_START_ISRC_RESET (AUX_TDC_TRIGSRC_START_SRC_AUX_ISRC_RESET_N) +#define AUXTDC_START_OBSMUX0 (AUX_TDC_TRIGSRC_START_SRC_MCU_OBSMUX0) +#define AUXTDC_START_OBSMUX1 (AUX_TDC_TRIGSRC_START_SRC_MCU_OBSMUX1) +#define AUXTDC_START_SMPH_AUTOTAKE_DONE (AUX_TDC_TRIGSRC_START_SRC_AUX_SMPH_AUTOTAKE_DONE) +#define AUXTDC_START_TDC_PRE (AUX_TDC_TRIGSRC_START_SRC_AUX_TDC_PRE) +#define AUXTDC_START_TIMER0_EV (AUX_TDC_TRIGSRC_START_SRC_AUX_TIMER0_EV) +#define AUXTDC_START_TIMER1_EV (AUX_TDC_TRIGSRC_START_SRC_AUX_TIMER1_EV) +#define AUXTDC_START_AON_RTC_CH2 (AUX_TDC_TRIGSRC_START_SRC_AON_RTC_CH2) +#define AUXTDC_START_AUX_COMPA (AUX_TDC_TRIGSRC_START_SRC_AUX_COMPA) +#define AUXTDC_START_AUX_COMPB (AUX_TDC_TRIGSRC_START_SRC_AUX_COMPB) #define AUXTDC_START_ACLK_REF (AUX_TDC_TRIGSRC_START_SRC_ACLK_REF) #define AUXTDC_START_MCU_EV (AUX_TDC_TRIGSRC_START_SRC_MCU_EV) -#define AUXTDC_START_TDC_PRE (AUX_TDC_TRIGSRC_START_SRC_TDC_PRE) //***************************************************************************** // @@ -286,19 +350,6 @@ AUXTDCStatusGet(uint32_t ui32Base) //! //! The \c ui32StartCondition must be a bitwise OR of the start event and the //! polarity of the start event. The start events are: -//! - \ref AUXTDC_START_AON_RTC_CH2 -//! - \ref AUXTDC_START_AUX_COMPA -//! - \ref AUXTDC_START_AUX_COMPB -//! - \ref AUXTDC_START_ISRC_RESET -//! - \ref AUXTDC_START_TIMER0_EV -//! - \ref AUXTDC_START_TIMER1_EV -//! - \ref AUXTDC_START_SMPH_AUTOTAKE_DONE -//! - \ref AUXTDC_START_ADC_DONE -//! - \ref AUXTDC_START_ADC_FIFO_ALMOST_FULL -//! - \ref AUXTDC_START_OBSMUX0 -//! - \ref AUXTDC_START_OBSMUX1 -//! - \ref AUXTDC_START_AON_SW -//! - \ref AUXTDC_START_AON_PROG_WU //! - \ref AUXTDC_START_AUXIO0 //! - \ref AUXTDC_START_AUXIO1 //! - \ref AUXTDC_START_AUXIO2 @@ -315,28 +366,60 @@ AUXTDCStatusGet(uint32_t ui32Base) //! - \ref AUXTDC_START_AUXIO13 //! - \ref AUXTDC_START_AUXIO14 //! - \ref AUXTDC_START_AUXIO15 +//! - \ref AUXTDC_START_AUXIO16 +//! - \ref AUXTDC_START_AUXIO17 +//! - \ref AUXTDC_START_AUXIO18 +//! - \ref AUXTDC_START_AUXIO19 +//! - \ref AUXTDC_START_AUXIO20 +//! - \ref AUXTDC_START_AUXIO21 +//! - \ref AUXTDC_START_AUXIO22 +//! - \ref AUXTDC_START_AUXIO23 +//! - \ref AUXTDC_START_AUXIO24 +//! - \ref AUXTDC_START_AUXIO25 +//! - \ref AUXTDC_START_AUXIO26 +//! - \ref AUXTDC_START_AUXIO27 +//! - \ref AUXTDC_START_AUXIO28 +//! - \ref AUXTDC_START_AUXIO29 +//! - \ref AUXTDC_START_AUXIO30 +//! - \ref AUXTDC_START_AUXIO31 +//! - \ref AUXTDC_START_MANUAL_EV +//! - \ref AUXTDC_START_AON_RTC_CH2_DLY +//! - \ref AUXTDC_START_AON_RTC_4KHZ +//! - \ref AUXTDC_START_AON_BATMON_BAT_UPD +//! - \ref AUXTDC_START_AON_BATMON_TEMP_UPD +//! - \ref AUXTDC_START_SCLK_LF +//! - \ref AUXTDC_START_PWR_DWN +//! - \ref AUXTDC_START_MCU_ACTIVE +//! - \ref AUXTDC_START_VDDR_RECHARGE +//! - \ref AUXTDC_START_TIMER2_EV0 +//! - \ref AUXTDC_START_TIMER2_EV1 +//! - \ref AUXTDC_START_TIMER2_EV2 +//! - \ref AUXTDC_START_TIMER2_EV3 +//! - \ref AUXTDC_START_TIMER2_PULSE +//! - \ref AUXTDC_START_TDC_DONE +//! - \ref AUXTDC_START_ADC_IRQ +//! - \ref AUXTDC_START_ADC_FIFO_NOT_EMPTY +//! - \ref AUXTDC_START_NO_EVENT +//! - \ref AUXTDC_START_ADC_DONE +//! - \ref AUXTDC_START_ADC_FIFO_ALMOST_FULL +//! - \ref AUXTDC_START_ISRC_RESET +//! - \ref AUXTDC_START_OBSMUX0 +//! - \ref AUXTDC_START_OBSMUX1 +//! - \ref AUXTDC_START_SMPH_AUTOTAKE_DONE +//! - \ref AUXTDC_START_TDC_PRE +//! - \ref AUXTDC_START_TIMER0_EV +//! - \ref AUXTDC_START_TIMER1_EV +//! - \ref AUXTDC_START_AON_RTC_CH2 +//! - \ref AUXTDC_START_AUX_COMPA +//! - \ref AUXTDC_START_AUX_COMPB //! - \ref AUXTDC_START_ACLK_REF //! - \ref AUXTDC_START_MCU_EV -//! - \ref AUXTDC_START_TDC_PRE //! //! The polarity of the start event is either rising \ref AUXTDC_STARTPOL_RIS //! or falling \ref AUXTDC_STARTPOL_FALL. //! //! The \c ui32StopCondition must be a bitwise OR of the stop event and the //! polarity of the stop event. The stop events are: -//! - \ref AUXTDC_STOP_AON_RTC_CH2 -//! - \ref AUXTDC_STOP_AUX_COMPA -//! - \ref AUXTDC_STOP_AUX_COMPB -//! - \ref AUXTDC_STOP_ISRC_RESET -//! - \ref AUXTDC_STOP_TIMER0_EV -//! - \ref AUXTDC_STOP_TIMER1_EV -//! - \ref AUXTDC_STOP_SMPH_AUTOTAKE_DONE -//! - \ref AUXTDC_STOP_ADC_DONE -//! - \ref AUXTDC_STOP_ADC_FIFO_ALMOST_FULL -//! - \ref AUXTDC_STOP_OBSMUX0 -//! - \ref AUXTDC_STOP_OBSMUX1 -//! - \ref AUXTDC_STOP_AON_SW -//! - \ref AUXTDC_STOP_AON_PROG_WU //! - \ref AUXTDC_STOP_AUXIO0 //! - \ref AUXTDC_STOP_AUXIO1 //! - \ref AUXTDC_STOP_AUXIO2 @@ -353,9 +436,54 @@ AUXTDCStatusGet(uint32_t ui32Base) //! - \ref AUXTDC_STOP_AUXIO13 //! - \ref AUXTDC_STOP_AUXIO14 //! - \ref AUXTDC_STOP_AUXIO15 +//! - \ref AUXTDC_STOP_AUXIO16 +//! - \ref AUXTDC_STOP_AUXIO17 +//! - \ref AUXTDC_STOP_AUXIO18 +//! - \ref AUXTDC_STOP_AUXIO19 +//! - \ref AUXTDC_STOP_AUXIO20 +//! - \ref AUXTDC_STOP_AUXIO21 +//! - \ref AUXTDC_STOP_AUXIO22 +//! - \ref AUXTDC_STOP_AUXIO23 +//! - \ref AUXTDC_STOP_AUXIO24 +//! - \ref AUXTDC_STOP_AUXIO25 +//! - \ref AUXTDC_STOP_AUXIO26 +//! - \ref AUXTDC_STOP_AUXIO27 +//! - \ref AUXTDC_STOP_AUXIO28 +//! - \ref AUXTDC_STOP_AUXIO29 +//! - \ref AUXTDC_STOP_AUXIO30 +//! - \ref AUXTDC_STOP_AUXIO31 +//! - \ref AUXTDC_STOP_MANUAL_EV +//! - \ref AUXTDC_STOP_AON_RTC_CH2_DLY +//! - \ref AUXTDC_STOP_AON_RTC_4KHZ +//! - \ref AUXTDC_STOP_AON_BATMON_BAT_UPD +//! - \ref AUXTDC_STOP_AON_BATMON_TEMP_UPD +//! - \ref AUXTDC_STOP_SCLK_LF +//! - \ref AUXTDC_STOP_PWR_DWN +//! - \ref AUXTDC_STOP_MCU_ACTIVE +//! - \ref AUXTDC_STOP_VDDR_RECHARGE +//! - \ref AUXTDC_STOP_TIMER2_EV0 +//! - \ref AUXTDC_STOP_TIMER2_EV1 +//! - \ref AUXTDC_STOP_TIMER2_EV2 +//! - \ref AUXTDC_STOP_TIMER2_EV3 +//! - \ref AUXTDC_STOP_TIMER2_PULSE +//! - \ref AUXTDC_STOP_TDC_DONE +//! - \ref AUXTDC_STOP_ADC_IRQ +//! - \ref AUXTDC_STOP_ADC_FIFO_NOT_EMPTY +//! - \ref AUXTDC_STOP_NO_EVENT +//! - \ref AUXTDC_STOP_ADC_DONE +//! - \ref AUXTDC_STOP_ADC_FIFO_ALMOST_FULL +//! - \ref AUXTDC_STOP_ISRC_RESET +//! - \ref AUXTDC_STOP_OBSMUX0 +//! - \ref AUXTDC_STOP_OBSMUX1 +//! - \ref AUXTDC_STOP_SMPH_AUTOTAKE_DONE +//! - \ref AUXTDC_STOP_TDC_PRE +//! - \ref AUXTDC_STOP_TIMER0_EV +//! - \ref AUXTDC_STOP_TIMER1_EV +//! - \ref AUXTDC_STOP_AON_RTC_CH2 +//! - \ref AUXTDC_STOP_AUX_COMPA +//! - \ref AUXTDC_STOP_AUX_COMPB //! - \ref AUXTDC_STOP_ACLK_REF //! - \ref AUXTDC_STOP_MCU_EV -//! - \ref AUXTDC_STOP_TDC_PRE //! //! The polarity of the stop event is either rising \ref AUXTDC_STOPPOL_RIS //! or falling \ref AUXTDC_STOPPOL_FALL. diff --git a/third_party/ti/devices/cc26x2/driverlib/bin/ccs/driverlib.lib b/third_party/ti/devices/cc13x2_cc26x2/driverlib/bin/ccs/driverlib.lib similarity index 58% rename from third_party/ti/devices/cc26x2/driverlib/bin/ccs/driverlib.lib rename to third_party/ti/devices/cc13x2_cc26x2/driverlib/bin/ccs/driverlib.lib index 609b11e9ee58b35f66cfd46d04d3cb10fd2a6c1e..0f663e6ce4978c8e81210bad8153175354c20abc 100644 GIT binary patch literal 1658276 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