Если вы когда‑либо работали с микроконтроллерами от компании Texas Instruments (TI), то 70%....90% вероятность, что вы их программировали в GUI‑IDE под названием Code Composer Studio (CCS). Как и у любой IDE CCS свойственны недостатки: ручные операции мышкой по настройке конфигураций, зависания GUI, отказ от сборки из консоли, калейдоскоп всяческих раcширений файлов, про которые даже местная техподдержка TI не в курсе, отказ от сборки проекта, если файл проекта находится вне пути на который ссылается переменная окружения WORKSPACE_LOC и прочее. Все эти проблемы можно разом решить, если собирать прошивки из самописных Makefile(ов) при помощи компилятора GNU ARM GCC.
О пользе makefile существует отдельный текст, вот он — Почему Важно Собирать С‑код из MakeFile. Если коротко, то с makefile(лами) намного проще делать полноценный DevOps, CI/CD и вообще масштабировать кодовую базу на другие процессорные архитектуры. Также сборка из makefile просто не позволяет разработчику производить неосознаных действий подобно тому как это повсеместно происходит в меню IDE.
Сборка прошивки для CC26x2 из Makefile
Фаза 1: подготовка оборудования, документации и софтвера
a--Что надо из оборудования?
# | оборудование |
1 | LapTop |
2 | отладочная плата LAUNCHXL-CC26X2R1 |
3 | кабель USB-A-USB micro |
В качестве отладочной платы я воспользуюсь платой LAUNCHXL-CC26X2R1. Там заложен микроконтроллер CC2652R1.

Вот примерная блок-схема платы LAUNCHXL-CC26X2R1. Мы видим, что тут есть сам микроконтроллер CC2652R1F и программатор отладчик XDS110.

Итак, что мы вообще знаем про микроконтроллер CC2652R1FRGZ?
Параметр | значение | Unit |
Ядро | Arm Cortex-M4F | -- |
Архитектура | ARMv7-M | |
RF Core | Arm Cortex-M0 | |
разрядность | 32 | bit |
FPU | IEEE 754-compliant single-precision | |
RAM start | 0x20000000 | hex |
GPRAM start | 0x11000000 | hex |
GPRAM size | 8 | kByte |
ROM start | 0 | hex |
FLASH_CCFG start | 0x00057fa8 (44тый сектор) | hex |
количество секторов Flash памяти | 44 | dec |
RAM size | 80 | kByte |
ROM size | 352 | kByte |
Flash sector size | 8 | kByte |
Cache SRAM size | 8 | kByte |
Peripherals | GPIO DAC UART ADC SPI I2C I2S AES TRNG Bluetooth 5.1, Timers MPU | - |
Prog Interface | JTAG | - |
CPU clock | 48 | MHz |
Pin number | 48 | pin |
GPIO count | 31 | pin |
Порядок байтов | little Endian | - |
Корпус микросхемы | RGZ (7-mm x 7-mm VQFN48) | |
Шаг между пинами | 0.5 | мм |
Все эти данные об внутреннем устройстве микроконтроллера CC2652R1FRGZ нужны для формирования корректных опций компилятору и для написания корректного скрипта для компоновщика (*.ld файл).
b--Какие нужны доки?
№ | Название дока | количество | комментарий |
1 | Using GCC/GDB With SimpleLink CC26xx/CC13xx | 33 | Перечень состава ToolChain(а) для GCC специально для TI MCU |
2 | CC2652R SimpleLink Multiprotocol 2.4 GHz Wireless MCU | 70 | флаер на микроконтроллер |
3 | CC13x2, CC26x2 SimpleLink Wireless MCU Technical Reference Manual | 2083 | спецификация микроконтроллера |
4 | Cortex-M3/M4F Instruction Set | 221 | Спецификация процессорного ядра |
5 | WCS037 LAUNCHXL-CC26X2R1 | 7 | схемотехника отладочной платы |
c--Что надо из софтвера?
# | Программа | назначение |
1 | OS Windows | операционная система |
2 | Eclipse | текстовый редактор |
3 | GNU Toolchain | компилятор, компоновщик, отладчик |
4 | UniFlash | прошивальщик |
9 | SmartRF Flash Programmer 2 | еще один прошивальщик |
10 | XDS Emulation Software (EMUPack) (64-bit Windows) | Набор утилит в котором есть GDB сервер для микроконтроллеров CC26x2 |
8 | C:\ti\simplelink_cc13xx_cc26xx_sdk_5_40_00_40 | Исходные коды инициализации периферии микроконтроллеров семейства cc26xx |
5 | Build tools for Windows | набор вспомогательных консольных утилит для сборки программ. make, rm |
12 | make | универсальная утилита, которая управляет конвейером последовательности запуска консольных утилит на основе скрипта makefile |
13 | grep | утилита поиска файлов по ключевому регулярному выражению которое есть внутри найденных файлов |
6 | gdb_agent_console.exe | утилита GDB сервера для микроконтроллеров от TI |
7 | arm-none-eabi-gdb.exe | универсальная утилита GDB клиента |
11 | Tera Term | Терминал последовательного COM порта для диалога с прошивкой по UART |
Проверить корректность установки GNU Toolchain можно выполнив команду arm-none-eabi-gcc --version в консоли Windows

Нужна утилита make. Её можно взять из состава MinGW.

Фаза 2: Подготовка скрипта настройки компоновщика.
Обычно сам С-код не особе аппаратно-зависмый. Наиболее аппаратно-зависимые исходники это файл настройки компоновщика. В GCC это *.ld файлы. Где же взять *.ld файл для микроконтроллера cc2652r1frgz? Ответ прост. Надо порыться прямо в SDK. При помощи утилиты grep я вскоре сузил место поиска до папки
C:\ti\simplelink_cc13xx_cc26xx_sdk_5_40_00_40\source\ti\devices\cc13x2_cc26x2\linker_files. Там и лежал подходящий файл разметки компоновщика cc26x2r1f.lds
/* @file cc26x2r1f.lds @brief CC26x2R1F rev2 linker configuration file for GNU compiler. */ /* Entry Point */ ENTRY( ResetISR ) /* System memory map */ MEMORY { /* Application is stored in and executes from internal flash */ FLASH (RX) : ORIGIN = 0x0, LENGTH = 0x57FA8 /* Customer Configuration Area (CCFG) */ FLASH_CCFG (RX) : ORIGIN = 0x57FA8, LENGTH = 88 /* Application uses internal RAM for data */ SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x14000 /* Application can use GPRAM region as RAM if cache is disabled in the CCFG (DEFAULT_CCFG_SIZE_AND_DIS_FLAGS.SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM = 0) */ GPRAM (RWX) : ORIGIN = 0x11000000, LENGTH = 0x2000 } /*. Highest address of the stack. Used in startup file .*/ _estack = ORIGIN(SRAM) + LENGTH(SRAM); /*end of SRAM .*/ /*. Generate a link error if heap and stack does not fit into RAM .*/ _Min_Heap_Size = 0; _Min_Stack_Size = 0x100; /* Section allocation in memory */ SECTIONS { .text : { _text = .; KEEP(*(.vectors)) *(.text*) *(.rodata*) *(.init) *(.fini*) *(.eh_frame*) _etext = .; } > FLASH = 0 .ARM.exidx : { __exidx_start = .; *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = .; } > FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > FLASH .init_array : { _init_array = .; KEEP(*(SORT(.init_array.*))) KEEP(*(.init_array*)) _einit_array = .; } > FLASH .data : { _data = .; *(vtable) *(.data*) _edata = .; } > SRAM AT > FLASH _ldata = LOADADDR(.data); .bss : { __bss_start__ = .; _bss = .; *(.bss*) *(COMMON) _ebss = .; __bss_end__ = .; } > SRAM .ccfg : { KEEP(*(.ccfg)); } > FLASH_CCFG /* User_heap_stack section, used to check that there is enough SRAM left */ ._user_heap_stack : { . = ALIGN(4); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(4); } > SRAM .gpram : { } > GPRAM }
Фаза 3: Подготовка startup кода
До запуска main() должен отрабатывать startup код. Где же найти файл для startup кода? Тут опять поиск grep(оп) внутри SDK по имени микроконтроллера и ключевому слову startup привел меня к файлу startup_gcc.c. У ST обычно startup написан на assembler, но у TI startup файл написан на С. Это хорошо и понятно. Внутри startup_gcc.c есть функция ResetISR(). Функция ResetISR инициализирует глобальные переменные (rwdata), обнуляет неинициализированные переменные (bss), активирует FPU и запускает функцию main(), а если main дала осечку - запускает зависание в бесконечном цикле. В startup коде также перечислены все обработчики прерываний для микроконтроллеров сс26x2.
/****************************************************************************** * Filename: startup_gcc.c * Revised: $Date: 2017-06-01 16:01:48 +0200 (Thu, 01 Jun 2017) $ * Revision: $Revision: 17804 $ * * Description: Startup code for CC26x2 device family for use with GCC. * ******************************************************************************/ //***************************************************************************** // Check if compiler is GNU Compiler //***************************************************************************** #if !(defined(__GNUC__)) #error "startup_gcc.c: Unsupported compiler!" #endif #include "../inc/hw_types.h" #include "../driverlib/setup.h" //***************************************************************************** // Macro for weak symbol aliasing //***************************************************************************** #define WEAK_ALIAS(x) __attribute__ ((weak, alias(#x))) //***************************************************************************** // Forward declaration of the reset ISR and the default fault handlers. //***************************************************************************** void ResetISR( void ); static void NmiSRHandler( void ); static void FaultISRHandler( void ); static void IntDefaultHandler( void ); extern int main( void ); // Default interrupt handlers void NmiSR(void) WEAK_ALIAS(NmiSRHandler); void FaultISR(void) WEAK_ALIAS(FaultISRHandler); void MPUFaultIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void BusFaultIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void UsageFaultIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void SVCallIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void DebugMonIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void PendSVIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void SysTickIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void GPIOIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void I2CIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void RFCCPE1IntHandler(void) WEAK_ALIAS(IntDefaultHandler); void PKAIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void AONRTCIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void UART0IntHandler(void) WEAK_ALIAS(IntDefaultHandler); void AUXSWEvent0IntHandler(void) WEAK_ALIAS(IntDefaultHandler); void SSI0IntHandler(void) WEAK_ALIAS(IntDefaultHandler); void SSI1IntHandler(void) WEAK_ALIAS(IntDefaultHandler); void RFCCPE0IntHandler(void) WEAK_ALIAS(IntDefaultHandler); void RFCHardwareIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void RFCCmdAckIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void I2SIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void AUXSWEvent1IntHandler(void) WEAK_ALIAS(IntDefaultHandler); void WatchdogIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void Timer0AIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void Timer0BIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void Timer1AIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void Timer1BIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void Timer2AIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void Timer2BIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void Timer3AIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void Timer3BIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void CryptoIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void uDMAIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void uDMAErrIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void FlashIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void SWEvent0IntHandler(void) WEAK_ALIAS(IntDefaultHandler); void AUXCombEventIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void AONProgIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void DynProgIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void AUXCompAIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void AUXADCIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void TRNGIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void OSCIntHandler(void) WEAK_ALIAS(IntDefaultHandler); void AUXTimer2IntHandler(void) WEAK_ALIAS(IntDefaultHandler); void UART1IntHandler(void) WEAK_ALIAS(IntDefaultHandler); void BatMonIntHandler(void) WEAK_ALIAS(IntDefaultHandler); //***************************************************************************** // The following are constructs created by the linker, indicating where the // the "data" and "bss" segments reside in memory. //***************************************************************************** extern uint32_t _ldata; extern uint32_t _data; extern uint32_t _edata; extern uint32_t _bss; extern uint32_t _ebss; extern uint32_t _estack; //***************************************************************************** //! The vector table. Note that the proper constructs must be placed on this to //! ensure that it ends up at physical address 0x0000.0000 or at the start of //! the program if located at a start address other than 0. //***************************************************************************** __attribute__ ((section(".vectors"), used)) void (* const g_pfnVectors[])(void) = { (void (*)(void))((unsigned long)&_estack), // 0 The initial stack pointer ResetISR, // 1 The reset handler NmiSR, // 2 The NMI handler FaultISR, // 3 The hard fault handler MPUFaultIntHandler, // 4 Memory Management (MemManage) Fault BusFaultIntHandler, // 5 The bus fault handler UsageFaultIntHandler, // 6 The usage fault handler 0, // 7 Reserved 0, // 8 Reserved 0, // 9 Reserved 0, // 10 Reserved SVCallIntHandler, // 11 Supervisor Call (SVCall) DebugMonIntHandler, // 12 Debug monitor handler 0, // 13 Reserved PendSVIntHandler, // 14 The PendSV handler SysTickIntHandler, // 15 The SysTick handler //--- External interrupts --- GPIOIntHandler, // 16 AON edge detect I2CIntHandler, // 17 I2C RFCCPE1IntHandler, // 18 RF Core Command & Packet Engine 1 PKAIntHandler, // 19 PKA Interrupt event AONRTCIntHandler, // 20 AON RTC UART0IntHandler, // 21 UART0 Rx and Tx AUXSWEvent0IntHandler, // 22 AUX software event 0 SSI0IntHandler, // 23 SSI0 Rx and Tx SSI1IntHandler, // 24 SSI1 Rx and Tx RFCCPE0IntHandler, // 25 RF Core Command & Packet Engine 0 RFCHardwareIntHandler, // 26 RF Core Hardware RFCCmdAckIntHandler, // 27 RF Core Command Acknowledge I2SIntHandler, // 28 I2S AUXSWEvent1IntHandler, // 29 AUX software event 1 WatchdogIntHandler, // 30 Watchdog timer Timer0AIntHandler, // 31 Timer 0 subtimer A Timer0BIntHandler, // 32 Timer 0 subtimer B Timer1AIntHandler, // 33 Timer 1 subtimer A Timer1BIntHandler, // 34 Timer 1 subtimer B Timer2AIntHandler, // 35 Timer 2 subtimer A Timer2BIntHandler, // 36 Timer 2 subtimer B Timer3AIntHandler, // 37 Timer 3 subtimer A Timer3BIntHandler, // 38 Timer 3 subtimer B CryptoIntHandler, // 39 Crypto Core Result available uDMAIntHandler, // 40 uDMA Software uDMAErrIntHandler, // 41 uDMA Error FlashIntHandler, // 42 Flash controller SWEvent0IntHandler, // 43 Software Event 0 AUXCombEventIntHandler, // 44 AUX combined event AONProgIntHandler, // 45 AON programmable 0 DynProgIntHandler, // 46 Dynamic Programmable interrupt // source (Default: PRCM) AUXCompAIntHandler, // 47 AUX Comparator A AUXADCIntHandler, // 48 AUX ADC new sample or ADC DMA // done, ADC underflow, ADC overflow TRNGIntHandler, // 49 TRNG event OSCIntHandler, // 50 Combined event from Oscillator control AUXTimer2IntHandler, // 51 AUX Timer2 event 0 UART1IntHandler, // 52 UART1 combined interrupt BatMonIntHandler // 53 Combined event from battery monitor }; //***************************************************************************** //! This is the code that gets called when the processor first starts execution //! following a reset event. Only the absolutely necessary set is performed, //! after which the application supplied entry() routine is called. Any fancy //! actions (such as making decisions based on the reset cause register, and //! resetting the bits in that register) are left solely in the hands of the //! application. //***************************************************************************** void ResetISR(void){ uint32_t *pSrc; uint32_t *pDest; // Final trim of device SetupTrimDevice(); // Copy the data segment initializers from FLASH to SRAM. pSrc = &_ldata; for(pDest = &_data; pDest < &_edata; ) { *pDest++ = *pSrc++; } // Zero fill the bss segment. __asm(" ldr r0, =_bss\n" " ldr r1, =_ebss\n" " mov r2, #0\n" " .thumb_func\n" "zero_loop:\n" " cmp r0, r1\n" " it lt\n" " strlt r2, [r0], #4\n" " blt zero_loop"); // Enable the FPU // CPACR is located at address 0xE000ED88 // Set bits 20-23 in CPACR to enable CP10 and CP11 coprocessors __asm(" ldr.w r0, =0xE000ED88\n" " ldr r1, [r0]\n" " orr r1, r1, #(0xF << 20)\n" " str r1, [r0]\n"); // Call the application's entry point. main(); // If we ever return signal Error FaultISR(); } //***************************************************************************** //! This is the code that gets called when the processor receives a NMI. This //! simply enters an infinite loop, preserving the system state for examination //! by a debugger. //***************************************************************************** static void NmiSRHandler(void){ while(1) { } } //***************************************************************************** //! This is the code that gets called when the processor receives a fault //! interrupt. This simply enters an infinite loop, preserving the system state //! for examination by a debugger. //***************************************************************************** static void FaultISRHandler(void){ while(1) { } } //***************************************************************************** //! This is the code that gets called when the processor receives an unexpected //! interrupt. This simply enters an infinite loop, preserving the system state //! for examination by a debugger. //***************************************************************************** static void IntDefaultHandler(void){ // Go into an infinite loop. while(1) { } }
Фаза 4: Подготовка области конфигурации устройства
Микроконтроллеры СС26x2 отличаются тем, что у TI MCU в последнем (43м) секторе Flash памяти лежит бинарная структура, которая отвечает за аппаратные настройки микросхемы. Там прописаны заводские конфигурации и пользовательские конфигурации. Такие как MAC адрес, настройка загрузчика, мощность излучения RF части. Этот последний сектор надо корректно проинициализировать или вообще не трогать с самой покупки микроконтроллера. За формирование конфигов устройства отвечает файл-исходник ccfg.c.
Если в последнем секторе вдруг окажутся случайные числа, то микроконтроллер просто не заведется при hot reset, а на проводе кварца будет какой-то случайный рваный сигнал.
/****************************************************************************** * Filename: ccfg.c * Revised: $Date: 2017-11-02 11:36:28 +0100 (Thu, 02 Nov 2017) $ * Revision: $Revision: 18030 $ * Description: Customer Configuration for: * CC13x2, CC13x4, CC26x2, CC26x4 device family (HW rev 2). *****************************************************************************/ #ifndef __CCFC_C__ #define __CCFC_C__ #include <stdint.h> #include "../inc/hw_types.h" #include "../inc/hw_ccfg.h" #include "../inc/hw_ccfg_simple_struct.h" //***************************************************************************** // Introduction // This file contains fields used by Boot ROM, startup code, and SW radio // stacks to configure chip behavior. // // Fields are documented in more details in hw_ccfg.h and CCFG.html in // DriverLib documentation (doc_overview.html -> CPU Domain Memory Map -> CCFG). // // PLEASE NOTE: // It is not recommended to do modifications inside the ccfg.c file. // This file is part of the CoreSDK release and future releases may have // important modifications and new fields added without notice. // The recommended method to modify the CCFG settings is to have a separate // <customer_ccfg>.c file that defines the specific CCFG values to be // overridden and then include the TI provided ccfg.c at the very end, // giving default values for non-overriden settings. // // Example: // #define SET_CCFG_BL_CONFIG_BOOTLOADER_ENABLE 0xC5 // Enable ROM boot loader // #define SET_CCFG_MODE_CONF_SCLK_LF_OPTION 0x3 // LF RCOSC // //---- Use default values for all others ---- // #include "<project-path>/source/ti/devices/<device>/startup_files/ccfg.c" // //***************************************************************************** //***************************************************************************** // Internal settings, forcing several bit-fields to be set to a specific value. //***************************************************************************** //##################################### // Force VDDR high setting (Higher output power but also higher power consumption) // This is also called "boost mode" // WARNING: CCFG_FORCE_VDDR_HH must not be set to 1 if running in external regulator mode. //##################################### #ifndef CCFG_FORCE_VDDR_HH #define CCFG_FORCE_VDDR_HH 0x0 // Use default VDDR trim // #define CCFG_FORCE_VDDR_HH 0x1 // Force VDDR voltage to the factory HH setting (FCFG1..VDDR_TRIM_HH) #endif //***************************************************************************** // Set the values of the individual bit fields. //***************************************************************************** //##################################### // Alternative DC/DC settings //##################################### #ifndef SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_ALT_DCDC_SETTING #define SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_ALT_DCDC_SETTING 0x0 // Alternative DC/DC setting enabled // #define SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_ALT_DCDC_SETTING 0x1 // Alternative DC/DC setting disabled #endif #if ( CCFG_FORCE_VDDR_HH ) #define SET_CCFG_MODE_CONF_1_ALT_DCDC_VMIN 0xC // Special VMIN level (2.5V) when forced VDDR HH voltage #else #ifndef SET_CCFG_MODE_CONF_1_ALT_DCDC_VMIN #define SET_CCFG_MODE_CONF_1_ALT_DCDC_VMIN 0x8 // 2.25V #endif #endif #ifndef SET_CCFG_MODE_CONF_1_ALT_DCDC_DITHER_EN #define SET_CCFG_MODE_CONF_1_ALT_DCDC_DITHER_EN 0x0 // Dithering disabled // #define SET_CCFG_MODE_CONF_1_ALT_DCDC_DITHER_EN 0x1 // Dithering enabled #endif #ifndef SET_CCFG_MODE_CONF_1_ALT_DCDC_IPEAK #define SET_CCFG_MODE_CONF_1_ALT_DCDC_IPEAK 0x0 // Peak current #endif //##################################### // XOSC override settings //##################################### #ifndef SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_XOSC_OVR // #define SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_XOSC_OVR 0x0 // Enable override #define SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_XOSC_OVR 0x1 // Disable override #endif #ifndef SET_CCFG_MODE_CONF_1_DELTA_IBIAS_INIT #define SET_CCFG_MODE_CONF_1_DELTA_IBIAS_INIT 0x0 // Delta = 0 #endif #ifndef SET_CCFG_MODE_CONF_1_DELTA_IBIAS_OFFSET #define SET_CCFG_MODE_CONF_1_DELTA_IBIAS_OFFSET 0x0 // Delta = 0 #endif #ifndef SET_CCFG_MODE_CONF_1_XOSC_MAX_START #define SET_CCFG_MODE_CONF_1_XOSC_MAX_START 0x10 // 1600us #endif //##################################### // Power settings //##################################### #ifndef SET_CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA #define SET_CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA 0xF // Signed delta value +1 to apply to the VDDR_TRIM_SLEEP target (0xF=-1=default=no compensation) #endif #ifndef SET_CCFG_MODE_CONF_DCDC_RECHARGE #define SET_CCFG_MODE_CONF_DCDC_RECHARGE 0x0 // Use the DC/DC during recharge in powerdown // #define SET_CCFG_MODE_CONF_DCDC_RECHARGE 0x1 // Do not use the DC/DC during recharge in powerdown #endif #ifndef SET_CCFG_MODE_CONF_DCDC_ACTIVE #define SET_CCFG_MODE_CONF_DCDC_ACTIVE 0x0 // Use the DC/DC during active mode // #define SET_CCFG_MODE_CONF_DCDC_ACTIVE 0x1 // Do not use the DC/DC during active mode #endif #if ( CCFG_FORCE_VDDR_HH ) #define SET_CCFG_MODE_CONF_VDDS_BOD_LEVEL 0x1 // Special setting to enable forced VDDR HH voltage #else #ifndef SET_CCFG_MODE_CONF_VDDS_BOD_LEVEL // #define SET_CCFG_MODE_CONF_VDDS_BOD_LEVEL 0x0 // VDDS BOD level is 2.0V #define SET_CCFG_MODE_CONF_VDDS_BOD_LEVEL 0x1 // VDDS BOD level is 1.8V (or 1.65V for external regulator mode) #endif #endif #ifndef SET_CCFG_MODE_CONF_VDDR_CAP #define SET_CCFG_MODE_CONF_VDDR_CAP 0x3A // Unsigned 8-bit integer representing the min. decoupling capacitance on VDDR in units of 100nF #endif #ifndef SET_CCFG_MODE_CONF_VDDR_TRIM_SLEEP_TC #define SET_CCFG_MODE_CONF_VDDR_TRIM_SLEEP_TC 0x1 // Temperature compensation on VDDR sleep trim disabled (default) // #define SET_CCFG_MODE_CONF_VDDR_TRIM_SLEEP_TC 0x0 // Temperature compensation on VDDR sleep trim enabled #endif //##################################### // Clock settings //##################################### #ifndef SET_CCFG_MODE_CONF_SCLK_LF_OPTION // #define SET_CCFG_MODE_CONF_SCLK_LF_OPTION 0x0 // LF clock derived from HF clock. Note: using this configuration will block the device from entering Standby mode. // #define SET_CCFG_MODE_CONF_SCLK_LF_OPTION 0x1 // External LF clock #define SET_CCFG_MODE_CONF_SCLK_LF_OPTION 0x2 // LF XOSC // #define SET_CCFG_MODE_CONF_SCLK_LF_OPTION 0x3 // LF RCOSC #endif #ifndef SET_CCFG_MODE_CONF_XOSC_CAP_MOD // #define SET_CCFG_MODE_CONF_XOSC_CAP_MOD 0x0 // Apply cap-array delta #define SET_CCFG_MODE_CONF_XOSC_CAP_MOD 0x1 // Don't apply cap-array delta #endif #ifndef SET_CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA #define SET_CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA 0xFF // Signed 8-bit value, directly modifying trimmed XOSC cap-array value #endif #ifndef SET_CCFG_EXT_LF_CLK_DIO #define SET_CCFG_EXT_LF_CLK_DIO 0x01 // DIO number if using external LF clock #endif #ifndef SET_CCFG_EXT_LF_CLK_RTC_INCREMENT #define SET_CCFG_EXT_LF_CLK_RTC_INCREMENT 0x800000 // RTC increment representing the external LF clock frequency #endif //##################################### // Special HF clock source setting //##################################### #ifndef SET_CCFG_MODE_CONF_XOSC_FREQ // #define SET_CCFG_MODE_CONF_XOSC_FREQ 0x0 // HF source is 48 MHz TCXO // #define SET_CCFG_MODE_CONF_XOSC_FREQ 0x1 // HF source is HPOSC (BAW) (only valid for CC2652RB) #define SET_CCFG_MODE_CONF_XOSC_FREQ 0x2 // HF source is a 48 MHz xtal // #define SET_CCFG_MODE_CONF_XOSC_FREQ 0x3 // HF source is a 24 MHz xtal (not supported) #endif //##################################### // Bootloader settings //##################################### #ifndef SET_CCFG_BL_CONFIG_BOOTLOADER_ENABLE #define SET_CCFG_BL_CONFIG_BOOTLOADER_ENABLE 0x00 // Disable ROM boot loader // #define SET_CCFG_BL_CONFIG_BOOTLOADER_ENABLE 0xC5 // Enable ROM boot loader #endif #ifndef SET_CCFG_BL_CONFIG_BL_LEVEL // #define SET_CCFG_BL_CONFIG_BL_LEVEL 0x0 // Active low to open boot loader backdoor #define SET_CCFG_BL_CONFIG_BL_LEVEL 0x1 // Active high to open boot loader backdoor #endif #ifndef SET_CCFG_BL_CONFIG_BL_PIN_NUMBER #define SET_CCFG_BL_CONFIG_BL_PIN_NUMBER 0xFF // DIO number for boot loader backdoor #endif #ifndef SET_CCFG_BL_CONFIG_BL_ENABLE // #define SET_CCFG_BL_CONFIG_BL_ENABLE 0xC5 // Enabled boot loader backdoor #define SET_CCFG_BL_CONFIG_BL_ENABLE 0xFF // Disabled boot loader backdoor #endif //##################################### // Debug access settings //##################################### #ifndef SET_CCFG_CCFG_TI_OPTIONS_TI_FA_ENABLE #define SET_CCFG_CCFG_TI_OPTIONS_TI_FA_ENABLE 0x00 // Disable unlocking of TI FA option. // #define SET_CCFG_CCFG_TI_OPTIONS_TI_FA_ENABLE 0xC5 // Enable unlocking of TI FA option with the unlock code #endif #ifndef SET_CCFG_CCFG_TAP_DAP_0_CPU_DAP_ENABLE // #define SET_CCFG_CCFG_TAP_DAP_0_CPU_DAP_ENABLE 0x00 // Access disabled #define SET_CCFG_CCFG_TAP_DAP_0_CPU_DAP_ENABLE 0xC5 // Access enabled if also enabled in FCFG #endif #ifndef SET_CCFG_CCFG_TAP_DAP_0_PWRPROF_TAP_ENABLE //#define SET_CCFG_CCFG_TAP_DAP_0_PWRPROF_TAP_ENABLE 0x00 // Access disabled #define SET_CCFG_CCFG_TAP_DAP_0_PWRPROF_TAP_ENABLE 0xC5 // Access enabled if also enabled in FCFG #endif #ifndef SET_CCFG_CCFG_TAP_DAP_0_TEST_TAP_ENABLE #define SET_CCFG_CCFG_TAP_DAP_0_TEST_TAP_ENABLE 0x00 // Access disabled //#define SET_CCFG_CCFG_TAP_DAP_0_TEST_TAP_ENABLE 0xC5 // Access enabled if also enabled in FCFG #endif #ifndef SET_CCFG_CCFG_TAP_DAP_1_PBIST2_TAP_ENABLE #define SET_CCFG_CCFG_TAP_DAP_1_PBIST2_TAP_ENABLE 0x00 // Access disabled // #define SET_CCFG_CCFG_TAP_DAP_1_PBIST2_TAP_ENABLE 0xC5 // Access enabled if also enabled in FCFG #endif #ifndef SET_CCFG_CCFG_TAP_DAP_1_PBIST1_TAP_ENABLE #define SET_CCFG_CCFG_TAP_DAP_1_PBIST1_TAP_ENABLE 0x00 // Access disabled // #define SET_CCFG_CCFG_TAP_DAP_1_PBIST1_TAP_ENABLE 0xC5 // Access enabled if also enabled in FCFG #endif #ifndef SET_CCFG_CCFG_TAP_DAP_1_AON_TAP_ENABLE #define SET_CCFG_CCFG_TAP_DAP_1_AON_TAP_ENABLE 0x00 // Access disabled // #define SET_CCFG_CCFG_TAP_DAP_1_AON_TAP_ENABLE 0xC5 // Access enabled if also enabled in FCFG #endif //##################################### // Alternative IEEE 802.15.4 MAC address //##################################### #ifndef SET_CCFG_IEEE_MAC_0 #define SET_CCFG_IEEE_MAC_0 0xFFFFFFFF // Bits [31:0] #endif #ifndef SET_CCFG_IEEE_MAC_1 #define SET_CCFG_IEEE_MAC_1 0xFFFFFFFF // Bits [63:32] #endif //##################################### // Alternative BLE address //##################################### #ifndef SET_CCFG_IEEE_BLE_0 #define SET_CCFG_IEEE_BLE_0 0xFFFFFFFF // Bits [31:0] #endif #ifndef SET_CCFG_IEEE_BLE_1 #define SET_CCFG_IEEE_BLE_1 0xFFFFFFFF // Bits [63:32] #endif //##################################### // Flash erase settings //##################################### #ifndef SET_CCFG_ERASE_CONF_CHIP_ERASE_DIS_N // #define SET_CCFG_ERASE_CONF_CHIP_ERASE_DIS_N 0x0 // Any chip erase request detected during boot will be ignored #define SET_CCFG_ERASE_CONF_CHIP_ERASE_DIS_N 0x1 // Any chip erase request detected during boot will be performed by the boot FW #endif #ifndef SET_CCFG_ERASE_CONF_BANK_ERASE_DIS_N // #define SET_CCFG_ERASE_CONF_BANK_ERASE_DIS_N 0x0 // Disable the boot loader bank erase function #define SET_CCFG_ERASE_CONF_BANK_ERASE_DIS_N 0x1 // Enable the boot loader bank erase function #endif //##################################### // Flash image valid //##################################### #ifndef SET_CCFG_IMAGE_VALID_CONF_IMAGE_VALID #define SET_CCFG_IMAGE_VALID_CONF_IMAGE_VALID 0x00000000 // Flash image vector table is at address 0x00000000 (default) // #define SET_CCFG_IMAGE_VALID_CONF_IMAGE_VALID <valid_vector_table_addr> // Flash image vector table is at address <valid_vector_table_addr> // #define SET_CCFG_IMAGE_VALID_CONF_IMAGE_VALID <invalid_vector_table_addr> // Flash image vector table address is invalid. ROM boot loader is called. #endif //##################################### // Flash sector write protection //##################################### #ifndef SET_CCFG_CCFG_PROT_31_0 #define SET_CCFG_CCFG_PROT_31_0 0xFFFFFFFF #endif #ifndef SET_CCFG_CCFG_PROT_63_32 #define SET_CCFG_CCFG_PROT_63_32 0xFFFFFFFF #endif #ifndef SET_CCFG_CCFG_PROT_95_64 #define SET_CCFG_CCFG_PROT_95_64 0xFFFFFFFF #endif #ifndef SET_CCFG_CCFG_PROT_127_96 #define SET_CCFG_CCFG_PROT_127_96 0xFFFFFFFF #endif //##################################### // Select between cache or GPRAM //##################################### #ifndef SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM // #define SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM 0x0 // Cache is disabled and GPRAM is available at 0x11000000-0x11001FFF #define SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM 0x1 // Cache is enabled and GPRAM is disabled (unavailable) #endif //##################################### // TCXO settings //##################################### #ifndef SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_TCXO #define SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_TCXO 0x1 // Deprecated. Must be set to 0x1. #endif #ifndef SET_CCFG_MODE_CONF_1_TCXO_TYPE #define SET_CCFG_MODE_CONF_1_TCXO_TYPE 0x1 // 1 = Clipped-sine type. //#define SET_CCFG_MODE_CONF_1_TCXO_TYPE 0x0 // 0 = CMOS type. #endif #ifndef SET_CCFG_MODE_CONF_1_TCXO_MAX_START #define SET_CCFG_MODE_CONF_1_TCXO_MAX_START 0x7F // Maximum TCXO startup time in units of 100us. #endif //***************************************************************************** // CCFG values that should not be modified. //***************************************************************************** #define SET_CCFG_SIZE_AND_DIS_FLAGS_SIZE_OF_CCFG 0x0058 #define SET_CCFG_SIZE_AND_DIS_FLAGS_DISABLE_FLAGS (CCFG_SIZE_AND_DIS_FLAGS_DISABLE_FLAGS_M >> CCFG_SIZE_AND_DIS_FLAGS_DISABLE_FLAGS_S) #if ( CCFG_FORCE_VDDR_HH ) #define SET_CCFG_MODE_CONF_VDDR_EXT_LOAD 0x0 // Special setting to enable forced VDDR HH voltage #else #define SET_CCFG_MODE_CONF_VDDR_EXT_LOAD 0x1 #endif #define SET_CCFG_MODE_CONF_RTC_COMP 0x1 #define SET_CCFG_MODE_CONF_HF_COMP 0x1 #define SET_CCFG_VOLT_LOAD_0_VDDR_EXT_TP45 0xFF #define SET_CCFG_VOLT_LOAD_0_VDDR_EXT_TP25 0xFF #define SET_CCFG_VOLT_LOAD_0_VDDR_EXT_TP5 0xFF #define SET_CCFG_VOLT_LOAD_0_VDDR_EXT_TM15 0xFF #define SET_CCFG_VOLT_LOAD_1_VDDR_EXT_TP125 0xFF #define SET_CCFG_VOLT_LOAD_1_VDDR_EXT_TP105 0xFF #define SET_CCFG_VOLT_LOAD_1_VDDR_EXT_TP85 0xFF #define SET_CCFG_VOLT_LOAD_1_VDDR_EXT_TP65 0xFF #define SET_CCFG_RTC_OFFSET_RTC_COMP_P0 0xFFFF #define SET_CCFG_RTC_OFFSET_RTC_COMP_P1 0xFF #define SET_CCFG_RTC_OFFSET_RTC_COMP_P2 0xFF #define SET_CCFG_FREQ_OFFSET_HF_COMP_P0 0xFFFF #define SET_CCFG_FREQ_OFFSET_HF_COMP_P1 0xFF #define SET_CCFG_FREQ_OFFSET_HF_COMP_P2 0xFF //***************************************************************************** // Concatenate bit fields to words. // DO NOT EDIT! //***************************************************************************** #define DEFAULT_CCFG_EXT_LF_CLK ( \ ((((uint32_t)( SET_CCFG_EXT_LF_CLK_DIO )) << CCFG_EXT_LF_CLK_DIO_S ) | ~CCFG_EXT_LF_CLK_DIO_M ) & \ ((((uint32_t)( SET_CCFG_EXT_LF_CLK_RTC_INCREMENT )) << CCFG_EXT_LF_CLK_RTC_INCREMENT_S ) | ~CCFG_EXT_LF_CLK_RTC_INCREMENT_M ) ) #define DEFAULT_CCFG_MODE_CONF_1 ( \ ((((uint32_t)( SET_CCFG_MODE_CONF_1_TCXO_TYPE )) << CCFG_MODE_CONF_1_TCXO_TYPE_S ) | ~CCFG_MODE_CONF_1_TCXO_TYPE_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_1_TCXO_MAX_START )) << CCFG_MODE_CONF_1_TCXO_MAX_START_S ) | ~CCFG_MODE_CONF_1_TCXO_MAX_START_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_1_ALT_DCDC_VMIN )) << CCFG_MODE_CONF_1_ALT_DCDC_VMIN_S ) | ~CCFG_MODE_CONF_1_ALT_DCDC_VMIN_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_1_ALT_DCDC_DITHER_EN )) << CCFG_MODE_CONF_1_ALT_DCDC_DITHER_EN_S ) | ~CCFG_MODE_CONF_1_ALT_DCDC_DITHER_EN_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_1_ALT_DCDC_IPEAK )) << CCFG_MODE_CONF_1_ALT_DCDC_IPEAK_S ) | ~CCFG_MODE_CONF_1_ALT_DCDC_IPEAK_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_1_DELTA_IBIAS_INIT )) << CCFG_MODE_CONF_1_DELTA_IBIAS_INIT_S ) | ~CCFG_MODE_CONF_1_DELTA_IBIAS_INIT_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_1_DELTA_IBIAS_OFFSET )) << CCFG_MODE_CONF_1_DELTA_IBIAS_OFFSET_S ) | ~CCFG_MODE_CONF_1_DELTA_IBIAS_OFFSET_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_1_XOSC_MAX_START )) << CCFG_MODE_CONF_1_XOSC_MAX_START_S ) | ~CCFG_MODE_CONF_1_XOSC_MAX_START_M ) ) #define DEFAULT_CCFG_SIZE_AND_DIS_FLAGS ( \ ((((uint32_t)( SET_CCFG_SIZE_AND_DIS_FLAGS_SIZE_OF_CCFG )) << CCFG_SIZE_AND_DIS_FLAGS_SIZE_OF_CCFG_S ) | ~CCFG_SIZE_AND_DIS_FLAGS_SIZE_OF_CCFG_M ) & \ ((((uint32_t)( SET_CCFG_SIZE_AND_DIS_FLAGS_DISABLE_FLAGS )) << CCFG_SIZE_AND_DIS_FLAGS_DISABLE_FLAGS_S ) | ~CCFG_SIZE_AND_DIS_FLAGS_DISABLE_FLAGS_M ) & \ ((((uint32_t)( SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_TCXO )) << CCFG_SIZE_AND_DIS_FLAGS_DIS_TCXO_S ) | ~CCFG_SIZE_AND_DIS_FLAGS_DIS_TCXO_M ) & \ ((((uint32_t)( SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM )) << CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM_S ) | ~CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM_M ) & \ ((((uint32_t)( SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_ALT_DCDC_SETTING )) << CCFG_SIZE_AND_DIS_FLAGS_DIS_ALT_DCDC_SETTING_S ) | ~CCFG_SIZE_AND_DIS_FLAGS_DIS_ALT_DCDC_SETTING_M ) & \ ((((uint32_t)( SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_XOSC_OVR )) << CCFG_SIZE_AND_DIS_FLAGS_DIS_XOSC_OVR_S ) | ~CCFG_SIZE_AND_DIS_FLAGS_DIS_XOSC_OVR_M ) ) #define DEFAULT_CCFG_MODE_CONF ( \ ((((uint32_t)( SET_CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA )) << CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA_S ) | ~CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_DCDC_RECHARGE )) << CCFG_MODE_CONF_DCDC_RECHARGE_S ) | ~CCFG_MODE_CONF_DCDC_RECHARGE_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_DCDC_ACTIVE )) << CCFG_MODE_CONF_DCDC_ACTIVE_S ) | ~CCFG_MODE_CONF_DCDC_ACTIVE_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_VDDR_EXT_LOAD )) << CCFG_MODE_CONF_VDDR_EXT_LOAD_S ) | ~CCFG_MODE_CONF_VDDR_EXT_LOAD_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_VDDS_BOD_LEVEL )) << CCFG_MODE_CONF_VDDS_BOD_LEVEL_S ) | ~CCFG_MODE_CONF_VDDS_BOD_LEVEL_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_SCLK_LF_OPTION )) << CCFG_MODE_CONF_SCLK_LF_OPTION_S ) | ~CCFG_MODE_CONF_SCLK_LF_OPTION_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_VDDR_TRIM_SLEEP_TC )) << CCFG_MODE_CONF_VDDR_TRIM_SLEEP_TC_S ) | ~CCFG_MODE_CONF_VDDR_TRIM_SLEEP_TC_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_RTC_COMP )) << CCFG_MODE_CONF_RTC_COMP_S ) | ~CCFG_MODE_CONF_RTC_COMP_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_XOSC_FREQ )) << CCFG_MODE_CONF_XOSC_FREQ_S ) | ~CCFG_MODE_CONF_XOSC_FREQ_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_XOSC_CAP_MOD )) << CCFG_MODE_CONF_XOSC_CAP_MOD_S ) | ~CCFG_MODE_CONF_XOSC_CAP_MOD_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_HF_COMP )) << CCFG_MODE_CONF_HF_COMP_S ) | ~CCFG_MODE_CONF_HF_COMP_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA )) << CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA_S ) | ~CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA_M ) & \ ((((uint32_t)( SET_CCFG_MODE_CONF_VDDR_CAP )) << CCFG_MODE_CONF_VDDR_CAP_S ) | ~CCFG_MODE_CONF_VDDR_CAP_M ) ) #define DEFAULT_CCFG_VOLT_LOAD_0 ( \ ((((uint32_t)( SET_CCFG_VOLT_LOAD_0_VDDR_EXT_TP45 )) << CCFG_VOLT_LOAD_0_VDDR_EXT_TP45_S ) | ~CCFG_VOLT_LOAD_0_VDDR_EXT_TP45_M ) & \ ((((uint32_t)( SET_CCFG_VOLT_LOAD_0_VDDR_EXT_TP25 )) << CCFG_VOLT_LOAD_0_VDDR_EXT_TP25_S ) | ~CCFG_VOLT_LOAD_0_VDDR_EXT_TP25_M ) & \ ((((uint32_t)( SET_CCFG_VOLT_LOAD_0_VDDR_EXT_TP5 )) << CCFG_VOLT_LOAD_0_VDDR_EXT_TP5_S ) | ~CCFG_VOLT_LOAD_0_VDDR_EXT_TP5_M ) & \ ((((uint32_t)( SET_CCFG_VOLT_LOAD_0_VDDR_EXT_TM15 )) << CCFG_VOLT_LOAD_0_VDDR_EXT_TM15_S ) | ~CCFG_VOLT_LOAD_0_VDDR_EXT_TM15_M ) ) #define DEFAULT_CCFG_VOLT_LOAD_1 ( \ ((((uint32_t)( SET_CCFG_VOLT_LOAD_1_VDDR_EXT_TP125 )) << CCFG_VOLT_LOAD_1_VDDR_EXT_TP125_S ) | ~CCFG_VOLT_LOAD_1_VDDR_EXT_TP125_M ) & \ ((((uint32_t)( SET_CCFG_VOLT_LOAD_1_VDDR_EXT_TP105 )) << CCFG_VOLT_LOAD_1_VDDR_EXT_TP105_S ) | ~CCFG_VOLT_LOAD_1_VDDR_EXT_TP105_M ) & \ ((((uint32_t)( SET_CCFG_VOLT_LOAD_1_VDDR_EXT_TP85 )) << CCFG_VOLT_LOAD_1_VDDR_EXT_TP85_S ) | ~CCFG_VOLT_LOAD_1_VDDR_EXT_TP85_M ) & \ ((((uint32_t)( SET_CCFG_VOLT_LOAD_1_VDDR_EXT_TP65 )) << CCFG_VOLT_LOAD_1_VDDR_EXT_TP65_S ) | ~CCFG_VOLT_LOAD_1_VDDR_EXT_TP65_M ) ) #define DEFAULT_CCFG_RTC_OFFSET ( \ ((((uint32_t)( SET_CCFG_RTC_OFFSET_RTC_COMP_P0 )) << CCFG_RTC_OFFSET_RTC_COMP_P0_S ) | ~CCFG_RTC_OFFSET_RTC_COMP_P0_M ) & \ ((((uint32_t)( SET_CCFG_RTC_OFFSET_RTC_COMP_P1 )) << CCFG_RTC_OFFSET_RTC_COMP_P1_S ) | ~CCFG_RTC_OFFSET_RTC_COMP_P1_M ) & \ ((((uint32_t)( SET_CCFG_RTC_OFFSET_RTC_COMP_P2 )) << CCFG_RTC_OFFSET_RTC_COMP_P2_S ) | ~CCFG_RTC_OFFSET_RTC_COMP_P2_M ) ) #define DEFAULT_CCFG_FREQ_OFFSET ( \ ((((uint32_t)( SET_CCFG_FREQ_OFFSET_HF_COMP_P0 )) << CCFG_FREQ_OFFSET_HF_COMP_P0_S ) | ~CCFG_FREQ_OFFSET_HF_COMP_P0_M ) & \ ((((uint32_t)( SET_CCFG_FREQ_OFFSET_HF_COMP_P1 )) << CCFG_FREQ_OFFSET_HF_COMP_P1_S ) | ~CCFG_FREQ_OFFSET_HF_COMP_P1_M ) & \ ((((uint32_t)( SET_CCFG_FREQ_OFFSET_HF_COMP_P2 )) << CCFG_FREQ_OFFSET_HF_COMP_P2_S ) | ~CCFG_FREQ_OFFSET_HF_COMP_P2_M ) ) #define DEFAULT_CCFG_IEEE_MAC_0 SET_CCFG_IEEE_MAC_0 #define DEFAULT_CCFG_IEEE_MAC_1 SET_CCFG_IEEE_MAC_1 #define DEFAULT_CCFG_IEEE_BLE_0 SET_CCFG_IEEE_BLE_0 #define DEFAULT_CCFG_IEEE_BLE_1 SET_CCFG_IEEE_BLE_1 #define DEFAULT_CCFG_BL_CONFIG ( \ ((((uint32_t)( SET_CCFG_BL_CONFIG_BOOTLOADER_ENABLE )) << CCFG_BL_CONFIG_BOOTLOADER_ENABLE_S ) | ~CCFG_BL_CONFIG_BOOTLOADER_ENABLE_M ) & \ ((((uint32_t)( SET_CCFG_BL_CONFIG_BL_LEVEL )) << CCFG_BL_CONFIG_BL_LEVEL_S ) | ~CCFG_BL_CONFIG_BL_LEVEL_M ) & \ ((((uint32_t)( SET_CCFG_BL_CONFIG_BL_PIN_NUMBER )) << CCFG_BL_CONFIG_BL_PIN_NUMBER_S ) | ~CCFG_BL_CONFIG_BL_PIN_NUMBER_M ) & \ ((((uint32_t)( SET_CCFG_BL_CONFIG_BL_ENABLE )) << CCFG_BL_CONFIG_BL_ENABLE_S ) | ~CCFG_BL_CONFIG_BL_ENABLE_M ) ) #define DEFAULT_CCFG_ERASE_CONF ( \ ((((uint32_t)( SET_CCFG_ERASE_CONF_CHIP_ERASE_DIS_N )) << CCFG_ERASE_CONF_CHIP_ERASE_DIS_N_S ) | ~CCFG_ERASE_CONF_CHIP_ERASE_DIS_N_M ) & \ ((((uint32_t)( SET_CCFG_ERASE_CONF_BANK_ERASE_DIS_N )) << CCFG_ERASE_CONF_BANK_ERASE_DIS_N_S ) | ~CCFG_ERASE_CONF_BANK_ERASE_DIS_N_M ) ) #define DEFAULT_CCFG_CCFG_TI_OPTIONS ( \ ((((uint32_t)( SET_CCFG_CCFG_TI_OPTIONS_TI_FA_ENABLE )) << CCFG_CCFG_TI_OPTIONS_TI_FA_ENABLE_S ) | ~CCFG_CCFG_TI_OPTIONS_TI_FA_ENABLE_M ) ) #define DEFAULT_CCFG_CCFG_TAP_DAP_0 ( \ ((((uint32_t)( SET_CCFG_CCFG_TAP_DAP_0_CPU_DAP_ENABLE )) << CCFG_CCFG_TAP_DAP_0_CPU_DAP_ENABLE_S ) | ~CCFG_CCFG_TAP_DAP_0_CPU_DAP_ENABLE_M ) & \ ((((uint32_t)( SET_CCFG_CCFG_TAP_DAP_0_PWRPROF_TAP_ENABLE )) << CCFG_CCFG_TAP_DAP_0_PWRPROF_TAP_ENABLE_S ) | ~CCFG_CCFG_TAP_DAP_0_PWRPROF_TAP_ENABLE_M ) & \ ((((uint32_t)( SET_CCFG_CCFG_TAP_DAP_0_TEST_TAP_ENABLE )) << CCFG_CCFG_TAP_DAP_0_TEST_TAP_ENABLE_S ) | ~CCFG_CCFG_TAP_DAP_0_TEST_TAP_ENABLE_M ) ) #define DEFAULT_CCFG_CCFG_TAP_DAP_1 ( \ ((((uint32_t)( SET_CCFG_CCFG_TAP_DAP_1_PBIST2_TAP_ENABLE )) << CCFG_CCFG_TAP_DAP_1_PBIST2_TAP_ENABLE_S ) | ~CCFG_CCFG_TAP_DAP_1_PBIST2_TAP_ENABLE_M ) & \ ((((uint32_t)( SET_CCFG_CCFG_TAP_DAP_1_PBIST1_TAP_ENABLE )) << CCFG_CCFG_TAP_DAP_1_PBIST1_TAP_ENABLE_S ) | ~CCFG_CCFG_TAP_DAP_1_PBIST1_TAP_ENABLE_M ) & \ ((((uint32_t)( SET_CCFG_CCFG_TAP_DAP_1_AON_TAP_ENABLE )) << CCFG_CCFG_TAP_DAP_1_AON_TAP_ENABLE_S ) | ~CCFG_CCFG_TAP_DAP_1_AON_TAP_ENABLE_M ) ) #define DEFAULT_CCFG_IMAGE_VALID_CONF SET_CCFG_IMAGE_VALID_CONF_IMAGE_VALID #define DEFAULT_CCFG_CCFG_PROT_31_0 SET_CCFG_CCFG_PROT_31_0 #define DEFAULT_CCFG_CCFG_PROT_63_32 SET_CCFG_CCFG_PROT_63_32 #define DEFAULT_CCFG_CCFG_PROT_95_64 SET_CCFG_CCFG_PROT_95_64 #define DEFAULT_CCFG_CCFG_PROT_127_96 SET_CCFG_CCFG_PROT_127_96 //***************************************************************************** // Customer Configuration Area in Lock Page //***************************************************************************** #if defined(__IAR_SYSTEMS_ICC__) __root const ccfg_t __ccfg @ ".ccfg" = #elif defined(__TI_COMPILER_VERSION__) #pragma DATA_SECTION(__ccfg, ".ccfg") #pragma RETAIN(__ccfg) const ccfg_t __ccfg = #else const ccfg_t __ccfg __attribute__((section(".ccfg"))) __attribute__((used)) = #endif { // Mapped to address DEFAULT_CCFG_EXT_LF_CLK , // 0x50003FA8 (0x50003xxx maps to last DEFAULT_CCFG_MODE_CONF_1 , // 0x50003FAC sector in FLASH. DEFAULT_CCFG_SIZE_AND_DIS_FLAGS , // 0x50003FB0 Independent of FLASH size) DEFAULT_CCFG_MODE_CONF , // 0x50003FB4 DEFAULT_CCFG_VOLT_LOAD_0 , // 0x50003FB8 DEFAULT_CCFG_VOLT_LOAD_1 , // 0x50003FBC DEFAULT_CCFG_RTC_OFFSET , // 0x50003FC0 DEFAULT_CCFG_FREQ_OFFSET , // 0x50003FC4 DEFAULT_CCFG_IEEE_MAC_0 , // 0x50003FC8 DEFAULT_CCFG_IEEE_MAC_1 , // 0x50003FCC DEFAULT_CCFG_IEEE_BLE_0 , // 0x50003FD0 DEFAULT_CCFG_IEEE_BLE_1 , // 0x50003FD4 DEFAULT_CCFG_BL_CONFIG , // 0x50003FD8 DEFAULT_CCFG_ERASE_CONF , // 0x50003FDC DEFAULT_CCFG_CCFG_TI_OPTIONS , // 0x50003FE0 DEFAULT_CCFG_CCFG_TAP_DAP_0 , // 0x50003FE4 DEFAULT_CCFG_CCFG_TAP_DAP_1 , // 0x50003FE8 DEFAULT_CCFG_IMAGE_VALID_CONF , // 0x50003FEC DEFAULT_CCFG_CCFG_PROT_31_0 , // 0x50003FF0 DEFAULT_CCFG_CCFG_PROT_63_32 , // 0x50003FF4 DEFAULT_CCFG_CCFG_PROT_95_64 , // 0x50003FF8 DEFAULT_CCFG_CCFG_PROT_127_96 , // 0x50003FFC }; #endif // __CCFC_C__
Фаза 5: Подключить к сборке Hardware Abstraction Layer (HAL)
С настройками системы определились. Теперь можно накропать небольшое приложение. Путь там будет GPIO, LEDs, SysTick, UART, NoRTOS, CLI.
Примеры по настройке периферии можно взять в SimpleLink SDK, например по этим адресам.
C:\ti\simplelink_cc13xx_cc26xx_sdk_5_40_00_40\examples\nortos\CC26X2R1_LAUNCHXL\drivers\gpiointerrupt
Для микроконтроллеров СС26x2 в качестве HAL выступает папка C:/ti/simplelink_cc13xx_cc26xx_sdk_5_40_00_40. Поэтому надо прописать пути к заголовочным файлам. Также производитель распространяет свой код HAL в виде предварительно скомпилированных бинарных библиотек (*.a файлики). В связи с этим для компоновщика надо прописать пути к библиотекам drivers_cc26x2.a, nortos_cc26x2.a и driverlib.lib
ifneq ($(SIMPLELINK_CC13X2_26X2_SDK_MK_INC),Y) SIMPLELINK_CC13X2_26X2_SDK_MK_INC=Y mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) $(info Build $(mkfile_path) ) OPT += -DHAS_SIMPLELINK_CC13X2_26X2_SDK SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR = C:/ti/simplelink_cc13xx_cc26xx_sdk_5_40_00_40 #@echo $(error SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR= $(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)) INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR) INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/devices INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/devices/cc13x2_cc26x2 INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/devices/cc13x2_cc26x2/driverlib INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/devices/cc13x2_cc26x2/driverlib/bin INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/devices/cc13x2_cc26x2/driverlib/bin/gcc INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/devices/cc13x2_cc26x2/inc INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/kernel/nortos INCDIR += -I$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/kernel/nortos/posix LIBS += $(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/drivers/lib/gcc/m4f/drivers_cc26x2.a LIBS += $(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/kernel/nortos/lib/gcc/m4f/nortos_cc26x2.a LIBS += $(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/devices/cc13x2_cc26x2/driverlib/bin/gcc/driverlib.lib LIBDIR += -L$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source LIBDIR += -L$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/kernel/nortos LIBDIR += -L$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/kernel/nortos/lib LIBDIR += -L$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/kernel/nortos/lib/gcc LIBDIR += -L$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/kernel/nortos/lib/gcc/m4f LIBDIR += -L$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/drivers/lib LIBDIR += -L$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/drivers/lib/gcc LIBDIR += -L$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/drivers/lib/gcc/m4f LIBDIR += -L$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/devices/cc13x2_cc26x2/driverlib LIBDIR += -L$(SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR)/source/ti/devices/cc13x2_cc26x2/driverlib/bin/gcc endif
Стоит заметить, что для сборки прошивки для СС2652 вообще не нужен оригинальный CMSIS, несмотря на то, что у микроконтроллера ядро ARM Cortex-M4.
Фаза 6: Написание Makefile(ов)
Самый высокоуровневый Makefile для конкретной сборки может выглядеть так
MK_PATH:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) #@echo $(error MK_PATH=$(MK_PATH)) WORKSPACE_LOC:=$(MK_PATH)../../ INCDIR += -I$(MK_PATH) INCDIR += -I$(WORKSPACE_LOC) TARGET=launchpad_bootloader_m include $(MK_PATH)config.mk ifeq ($(CLI),Y) include $(MK_PATH)cli_config.mk endif ifeq ($(DIAG),Y) include $(MK_PATH)diag_config.mk endif include $(WORKSPACE_LOC)code_base.mk include $(WORKSPACE_LOC)rules.mk
Тут только подключение и передача конфигов (config.mk) для данной конкретной сборки, подключение кодовой базы (code_base.mk) и подключение привил сборки кодовой базы (rules.mk). На самом деле даже этот Makefile файл можно сделать общим. Разными будут только config.mk файлики.
Потом для каждого программного компонента можно составить *.mk файл примерно такой структуры. Код, диагностика, система команд для каждого конкретного программного компонента.
$(info LED_MONO_MK_INC=$(LED_MONO_MK_INC)) ifneq ($(LED_MONO_MK_INC),Y) LED_MONO_MK_INC=Y mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) $(info Build LED Mono) #FLASH_FS_DIR = $(WORKSPACE_LOC)Drivers/flash_fs LED_MONO_DIR = $(LED_GENERAL_DIR)/led_mono #@echo $(error LED_MONO_DIR=$(LED_MONO_DIR)) ifneq ($(LED),Y) @echo $(error Add General LED driver) endif INCDIR += -I$(LED_MONO_DIR) SOURCES_C += $(LED_MONO_DIR)/led_mono_drv.c OPT += -DHAS_LED_MONO OPT += -DHAS_LED_MONO_PROC MATH=Y ifeq ($(DIAG),Y) ifeq ($(LED_MONO_DIAG),Y) OPT += -DHAS_LED_MONO_DIAG SOURCES_C += $(LED_MONO_DIR)/led_mono_diag.c endif endif ifeq ($(CLI),Y) ifeq ($(LED_MONO_COMMANDS),Y) OPT += -DHAS_LED_MONO_COMMANDS SOURCES_C += $(LED_MONO_DIR)/led_mono_commands.c endif endif endif
В makefile надо указать какое ядро. Надо создать отдельный cortex_m4.mk файл и определить в нем опции компилятора для определения микропроцессорного ядра
$(info CORTEX_M4_MK_INC=$(CORTEX_M4_MK_INC) ) ifneq ($(CORTEX_M4_MK_INC),Y) CORTEX_M4_MK_INC=Y mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) $(info Build $(mkfile_path) ) CORTEX_M4_DIR = $(WORKSPACE_LOC)core/cortex_m4 INCDIR += -I$(CORTEX_M4_DIR) #@echo $(error CORTEX_M4_DIR=$(CORTEX_M4_DIR)) MCU=Y SOURCES_C += $(CORTEX_M4_DIR)/cortex_m4_driver.c ifeq ($(DIAG),Y) ifeq ($(CORTEX_M4_DIAG),Y) SOURCES_C += $(CORTEX_M4_DIR)/cortex_m4_diag.c endif endif OPT += -DHAS_ARM OPT += -DHAS_CORTEX_M4 OPT += -DHAS_CORTEX_M CPU = -mcpu=cortex-m4 -march=armv7e-m FPU = -mfpu=fpv4-sp-d16 # float-abi FLOAT-ABI = -mfloat-abi=hard # mcu MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI) ifeq ($(SYSTICK),Y) #@echo $(error SYSTICK=$(SYSTICK)) include $(CORTEX_M4_DIR)/systick/systick.mk endif endif
Также нужен специфичный *.mk файл для микроконтроллера CC2652R1FRGZ
#protection against repeated include as in C preprocessor $(info CC2652R1FRGZ_MK_INC=$(CC2652R1FRGZ_MK_INC) ) ifneq ($(CC2652R1FRGZ_MK_INC),Y) CC2652R1FRGZ_MK_INC=Y CC2652R1FRGZ_DIR = $(MCU_DIR)/cc2652r1f ifeq ($(CC2652),Y) OPT += -DHAS_CC2652 CC26X2=Y OPT += -DDeviceFamily_CC26X2 OPT += -DHAS_CC26x2 OPT += -DHAS_CC26X2 OPT += -DHAS_CC26XX OPT += -DCC26XX OPT += -DCC26x2 endif ifeq ($(CC2652R1FRGZ),Y) OPT += -DCC2652R1F OPT += -DHAS_CC2652R1F OPT += -DCC2652R1FRGZ OPT += -DHAS_CC2652R1FRGZ endif mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) $(info Build $(mkfile_path) ) FIRMWARE_TYPE_SELECTED=N BOARD=Y MICROCONTROLLER=Y CC2652R1FRGZ=Y INCDIR += -I$(CC2652R1FRGZ_DIR) ifeq ($(BOOTLOADER),Y) # link script FIRMWARE_TYPE_SELECTED=Y LDSCRIPT = $(CC2652R1FRGZ_DIR)/cc26x2r1f.lds endif ifeq ($(GPIO),Y) SOURCES_C += $(CC2652R1FRGZ_DIR)/cc2652R1F.c endif SOURCES_C += $(CC2652R1FRGZ_DIR)/startup_gcc.c SOURCES_C += $(CC2652R1FRGZ_DIR)/ccfg.c SOURCES_C += $(CC2652R1FRGZ_DIR)/syscalls.c ifeq ($(SYSTICK),Y) SOURCES_C += $(CC2652R1FRGZ_DIR)/systick_general_config.c endif MCU_SELECTED=Y endif
И, конечно же, основной универсальный для всех MCU rules.mk файл с правилами сборки можно написать примерно так:
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) $(info Build $(mkfile_path) ) BUILD_DIR = build INCDIR := $(subst /cygdrive/c/,C:/, $(INCDIR)) #@echo $(error INCDIR=$(INCDIR)) SOURCES_C := $(subst /cygdrive/c/,C:/, $(SOURCES_C)) #@echo $(error SOURCES_C=$(SOURCES_C)) SOURCES_ASM := $(subst /cygdrive/c/,C:/, $(SOURCES_ASM)) #@echo $(error SOURCES_ASM=$(SOURCES_ASM)) LIBS := $(subst /cygdrive/c/,C:/, $(LIBS)) LDSCRIPT := $(subst /cygdrive/c/,C:/, $(LDSCRIPT)) #@echo $(error SOURCES_ASM=$(SOURCES_ASM)) include $(WORKSPACE_LOC)/toolchain.mk # CFLAGS #https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html FLOAT-ABI = -mfloat-abi=hard MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI) # macros for gcc #CSTANDARD = -std=c11 CSTANDARD = -std=gnu99 AS_DEFS = AS_INCLUDES = ifeq ($(DEBUG), Y) CFLAGS += -g3 -ggdb -gdwarf-2 OPT += -O0 else OPT += -Os endif OPT += -fmessage-length=0 OPT += -fsigned-char OPT += -fno-common OPT += -fstack-usage OPT += -finline-small-functions #Perform dead code elimination OPT += -fdce #Perform dead store elimination OPT += -fdse ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections CFLAGS += $(CSTANDARD) CFLAGS += -Wall #CFLAGS += -Wformat-overflow=1 CFLAGS += $(MCU) $(OPT) -fdata-sections -ffunction-sections $(INCDIR) # Generate dependency information CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" # libraries LINKER_FLAGS += -Xlinker --gc-sections ifeq ($(MBR), Y) LIBS += -lnosys LDFLAGS += -specs=nano.specs else LINKER_FLAGS += -u _scanf_float LINKER_FLAGS += -u _printf_float endif ifeq ($(LIBC), Y) LIBS += -lc endif ifeq ($(MATH), Y) LIBS += -lm endif #@echo $(error LDSCRIPT=$(LDSCRIPT)) LIBDIR = LDFLAGS += $(MCU) -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections $(LINKER_FLAGS) # default action: build all all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin # build the application # list of objects OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(SOURCES_C:.c=.o))) vpath %.c $(sort $(dir $(SOURCES_C))) # list of ASM program objects OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(SOURCES_ASM:.S=.o))) vpath %.S $(sort $(dir $(SOURCES_ASM))) $(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ $(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR) $(AS) -c $(CFLAGS) $< -o $@ $(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile $(CC) $(OBJECTS) $(LDFLAGS) -o $@ $(SZ) $@ $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR) $(HEX) $< $@ $(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR) $(BIN) $< $@ $(BUILD_DIR): mkdir $@ # clean up clean: -rm -fR $(BUILD_DIR) # dependencies -include $(wildcard $(BUILD_DIR)/*.d) # *** EOF ***
Прелесть makefile в том, что для инициализации сборки достаточно открыть консоль и набрать make all. Затем, через пару минут в соседней папке появятся артефакты. При этом можно еще сохранить в файл полный лог для анализа, а не разглядывать последние 4 экрана как в CCS.
echo off cls make clean 2>&1 | tee clean_log.txt make 2>&1 | tee build_log.txt
Итак, прошивка собирается.

вот такие получились артефакты: *.bin, *.hex, *.map, *.elf

Фаза 7: Запись прошивки в on-chip NOR Flash память
Записать прошивку в микроконтроллер СС2652 тоже можно из консоли утилитой srfprog.exe. Эта утилита входит в состав программы SmartRF Flash Programmer 2. Обычно после установки утилита srfprog живет по адресу
C:\Program Files (x86)\Texas Instruments\SmartRF Tools\Flash Programmer 2\bin\srfprog.exe
Но если забыли, то всегда можно набрать запрос в Win консоли where srfprog.

Вот этот скрипт загружает прошивку в on-chip NOR Flash память микроконтроллера.
echo off cls set project_dir=%~dp0 set FLASH_TOOL=srfprog.exe set BIN_PATH=%project_dir%build\launchpad_bootloader_m.bin call %FLASH_TOOL% --list all call %FLASH_TOOL% --help call %FLASH_TOOL% --target lsidx(0) --erase all --program --file %BIN_PATH% --address 0
Обычно такой вывод информирует об успешной загрузке бинаря
Texas Instruments SmartRF Flash Programmer 2 v1.8.2-windows ------------------------------------------------------------------------------- Connected over 2-pin cJTAG. Reading file: C:\....\code_base_firmware\source\projects\launchpad_bootloader_m\build\launchpad_bootloader_m.bin. 2%le size: 360448 bytes. Number of assigned pages: 44. About 34 percent of the file contain assigned code. Start flash erase ... OK Start flash programming ... 100% OK Reset target ... OK C:\....\code_base_firmware\source\projects\launchpad_bootloader_m>
Однако 80..97% вероятность, что после первой же записи бинаря во flash прошивка где-нибудь зависнет, устройство превратится в тыкву. Причем прошивка зависнет где-то в инициализации, еще до запуска суперцикла. Поэтому надо сразу настроить пошаговую отладку через JTAG.
Фаза 8: Запуск GDB сервера
В качестве GDB сервера у TI выступает утилита gdb_agent_console.exe. Для корректного запуска утилиты gdb_agent_console ей надо передать конфигурационный *.dat файл для настройки конкретного отладчика. В случае с платой LAUNCHXL-CC26X2R1 надо выбрать отладчик XDS110. В очередной раз путем grep(ания) на жестком диске, я наткнулся вот на такой файл CC2652_XDS110_JTAG.dat. Причем *.dat файл оказался в папке пользователя а не в SDK.
# config version=3.5 $ sepk pod_drvr=jioxds110.dll pod_port=0 pod_supply=1 pod_voltage_selection=1 pod_voltage=3.3 $ / $ product title="Texas Instruments XDS110 USB" alias=TI_XDS110_USB name=XDS110 $ / $ uscif tdoedge=FALL tclk_program=DEFAULT tclk_frequency=2.5MHz jtag_isolate=disable $ / $ dot7 dts_usage=enable dts_type=xds110 dts_program=emulator dts_frequency=1.0MHz ts_format=jscan0 ts_pin_width=all_four $ / $ swd swd_debug=disabled swo_data=aux_uart $ / @ icepick_c family=icepick_c irbits=6 drbits=1 subpaths=2 & subpath_2 address=0 default=no custom=yes force=yes pseudo=no @ bypass_0 family=bypass irbits=4 drbits=1 & subpath_0 address=16 default=no custom=yes force=yes pseudo=no @ cs_dap_0 family=cs_dap irbits=4 drbits=1 subpaths=1 identify=0x4BA00477 revision=Legacy systemresetwhileconnected=1 & subpath_1 type=debug address=0 default=no custom=yes force=yes pseudo=no @ cortex_m4_0 family=cortex_mxx irbits=0 drbits=0 identify=0x02000000 traceid=0x0 & / & / # /
Вот скрипт для запуска GDB сервера.
set GDB_SERVER=C:\ti\ccs_base\common\uscif\gdb_agent_console.exe set USB_JTAG_CONFIG=%CUR_DIR%\CC2652_XDS110_JTAG.dat %GDB_SERVER% --help %GDB_SERVER% %USB_JTAG_CONFIG%
В консоли появляется лог сообщения об ожидании подключения на порте 55000

Вот такой текст вывалится в консоль как только GDB клиент подключится к GDB серверу
Фаза 9: GDB клиент
Для запуска GDB клиента надо открыть Win консоль и запустить утилиту arm-none-eabi-gdb.exe, передав ей путь к *.elf файлу с прошивкой. При этом прошивку надо было предварительно собрать с опцией -g.
cls set GDB_CLIENT="C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin\arm-none-eabi-gdb.exe" %GDB_CLIENT% --help set ELF_FILE=%CUR_DIR%\build\launchpad_bootloader_m.elf %GDB_CLIENT% --nw %ELF_FILE%
Чтобы подключится к микроконтроллеру надо внутри GDB клиента исполнить команду
target remote localhost:55000
Это нужно для того, чтобы подключиться к локальному порту с номеров 55000. И вот началась пошаговая отладка. Если вы спросите:
какая команда GDB клиента оказывается самой полезной?
, то я бы сказал, что это команда backtrace (bt). Именно команда backtrace покажет вам по какой причине прошивка свалилась в FaultISRHandler().

Вообще все известные полезные GDB команды у меня перечислены тут
https://docs.google.com/spreadsheets/d/1AWD8GsDfaA9dtdsfqgbB1klagou1yrREc1AAK9CRUik/edit#gid=0
Взаимодействие отладочных утилит можно показать вот такой блок-схемой

Как понять что прошивка завелась?
Достаточно посмотреть на Heartbeat LED. Если мигает значит суперцикл прошивки вертится. Удалось настроить окружение для разработки артефактов и собрать NoRTOS-прошивку для микроконтроллера СС2652 с GPIO, SysTick, LED, UART, CLI. Вот примерный лог загрузки и отладочная CLI в UART. Отладочная консоль отвечает на команды. Значит прошивка завелась. Успех!

То что вы сейчас видели (Debug CLI Terminal) это UART‑CLI. Про это есть отдельная хорошая история тут — Почему нам нужен UART‑Shell? (или 23 новые возможности).
Итак, всё вышесказанное можно упаковать в одну ёмкую схему ToolChain(на). Это и есть вся система сборки для СС26×2 на основе ARM GCC. Всё на одном листике.

Вывод
Удалось научиться собирать артефакты для микроконтроллеров компании Texas Instruments CC2652 компилятором ARM GCC непосредственно из Makefile(ов). Это является альтернативным и более классическим способом сборки артефактов по отношению к сборке из GUI-IDE CCS. При этом оказалось, что версионному контролю надо подвергнуть всего-навсего 6 расширений файлов *.с *.h *.lds *.mk *.makefile, *.dat. Сборка из Makefile помогает легко и эффективно масштабировать, мигрировать и конфигурировать общую кодовую базу.
Cловарь
Акроним | Расшифровка |
CDT | C/C++ Development Tooling |
RAM | random access memory |
HAL | Hardware Abstraction Layer |
OS | operating system |
SRAM | static RAM |
RISC | reduced instruction set computer |
ARM | Advanced RISC Machines |
CMSIS | Cortex Microcontroller Software Interface |
SDK | software development kit |
GNU | GNU’s Not UNIX |
CPU | central processing unit |
ROM | Read-only memory |
GCC | The GNU Compiler Collection |
GDB | The GNU Project Debugger |
IDE | Integrated Development Environment |
JTAG | Joint Test Action Group |
JRE | Java Runtime Environment |
CCA | Customer Configuration Area |
UNIX | UNiplexed Information Computing System |
CCFG | Customer Configuration section |
TI | Texas Instruments |
FPU | Floating Point Unit |
Links
https://developer.arm.com/Tools and Software/GNU Toolchain
https://github.com/wufucious/sensortag-blink/tree/f65459dbc182a7c6e2d356f7de033e93d0b7f05b
https://electrolama.com/radio-docs/flash-ti-flash-prog/
https://wiki.st.com/stm32mpu/wiki/GDB_commands
https://habr.com/ru/companies/unwds/articles/390815/
https://habr.com/ru/articles/430732/
https://habr.com/ru/articles/148169/
https://habr.com/ru/articles/162737/
https://docs.google.com/spreadsheets/d/1AWD8GsDfaA9dtdsfqgbB1klagou1yrREc1AAK9CRUik/edit#gid=0
Контрольные вопросы:
1--Что происходит c микроконтроллером между подачей питания и запуском функции main()?
2--Какие расширения файлов надо подвергать ве��сионному контролю при сборке через GCC и MakeFile?
3--Что является артефактами при сборке прошивки для микроконтроллера? Какие расширения у файлов артефактов?
4--Какой путь проходит код с момента написания до попадания в flash память?
5--Какие доки(спеки) нужны для того, чтобы разрабатывать встраиваемый софт? Назовите минимум 4 дока.
6--Компилятору подали 5 *.с файликов и 20 *.h файликов. Сколько будет *.o файликов?
7--В каких случаях артефакты в *.hex файликах предпочтительнее артефактов в *.bin файликах?
