Если вы когда‑либо работали с микроконтроллерами от компании 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 файликах?
Комментарии (18)
progchip666
12.04.2023 03:43Спасибо. Интересно, но лично для меня, скорее в качестве пищи для ума, чем практического применения. TI и STM итак имеют очень приличные среды разработки.
В сегодняшних условиях скорее китайские клоны актуальны, но по ним я так понимаю и информацию гораздо сложнее найти чем по TI
aabzel Автор
12.04.2023 03:43-3TI и STM итак имеют очень приличные среды разработки.
Это они специально для детей делают такие IDE.
aabzel Автор
12.04.2023 03:43-1STM итак имеет очень приличные среды разработки.
У меня есть еще методичка как собирать STM32 из MakeFile. https://habr.com/ru/articles/673522/Там всё очень просто.
progchip666
12.04.2023 03:43+2В моей практике один раз пришлось лезть в MakeFile, когда бутлоадер делал
aabzel Автор
12.04.2023 03:43-2Раз не было нужды в Makefile значит у Вас не было командной работы над одной общей кодовой базой, значит у Вас не было модульности в коде, значит у Вас была одна-две сборки на всё, значит у Вас не было сервера сборки, значит у Вас было тотальное дублирование конфигов, значит у Вас не было никакого DevOps(а).
Поэтому и не приходилось Вам разбираться с MakeFile.
Что ж для маленьких Pet-проектов использование IDE может быть и оправдано.
DmitryZlobec
12.04.2023 03:43+3До запуска main() должен отрабатывать startup код. Где же найти файл для startup кода?
Это вроде называется crt0. https://ru.wikipedia.org/wiki/Crt0
Вообще можно использовать Clion, у них сейчас нормальная поддержка Makefile. Другое дело что он платный.(
aabzel Автор
12.04.2023 03:43+1Может в desktop разработке и crt0. Просто в мире микроконтроллеров вендоры чипов обычно называют код до main префиксом statrup_*****.[Sc]
lolikandr
12.04.2023 03:43+11--Что происходит до запуска функции main()?
Startup code, иногда не отделимый от компилятора, который обнуляет статические и глобальные переменные в стандартных секциях и вызывает их конструкторы.
2--Какие расширения файлов надо подвергать версионному контролю при сборке через GCC и MakeFile?
Кратко - всё, что не сгенерируется. И лучше всё же настроить .gitignore, в котором указано то, что не надо.
3--Что является артефактами при сборке прошивки для микроконтроллера?
Файлы, которые потом используют для прошивки флэш или для тестов и для отладки.
4--Какой путь проходит код с момента написания до попадания в flash память?
Коммит - пуш - чек стиля - юниттесты - препроцессор-компиляция-линковка - выделение бинарника - скачиваемый артефакт - прошивка во флэш.
5--Какие доки(спеки) нужны для того, чтобы разрабатывать встраиваемый софт? Назовите минимум 4 дока.
Схема электрическая принципиальная, описание чипа и его периферии, эррата на чип, описание c/c++/asm. Некоторые описания слишком большие и TI разбивает их на эн пдф-файлов.
6--Компилятору подали 5 *.с файликов и 20 *.h файликов. Сколько будет *.o файликов?
Обычно 5.
7--В каких случаях артефакты в *.hex файликах предпочтительнее артефактов в *.bin файликах?
Зависит от программатора и способа обновления прошивки, особенно если шить напрямую во флэш.aabzel Автор
12.04.2023 03:43Хорошие ответы! Есть еще полный тест
https://habr.com/ru/articles/676076/там самые адекватные вопросы собраны за 12 лет
aabzel Автор
12.04.2023 03:43.hex лучше .bin так как для .hex не надо отдельно указывать адрес старта прошивки.
Сколько случаев было когда техники загрузчик в *.bin записывали в область generic, а потом удивлялись почему не работает...
Javian
Мне понравилась Energia IDE https://energia.nu/ — функциональный аналог Arduino IDE вместо профессионального Code Composer Studio.
P.S. а что сейчас с доступностью и ценами в РФ на продукцию TI от MSP430 и т.п.
progchip666
всё очень плохо. Мы в поисках альтернатив
aabzel Автор
Нужен вообще полностью российский 32 бит RISC микроконтроллер с уникальным ядром (не ARM Cortex M). Изготовляемый на территории РФ начиная с выращивания кристалла для кремниевых пластин.
Потом нужна российская операционная системы для PC, российский компилятор для МК и даже текстовый редактор.
Тогда только и можно будет говорить про суверенитет.
progchip666
Такой суверинитет дорого стоит. Если вы немного подумаете своей головой и прикините объёмы продаж своего полностью российского процессора, учтёте что его невозможно сделать без поддержки государства, а поддержка государства связана с коррупцией, особенно в наших условиях (и коррупция ещё не самое страшное зло) то выяснится что и ядро и даже микроконтроллер сделать то в принципе можно(вопрос за какое время) вот только стоить всё это вместе с собственным производством будет столько, что купить его смогут военные за государственные же деньги. У СССР был СЭВ, не маленькая такая структура и то с треском проиграла гонку когда компьютеры стали персональными. Сегодняшняя система нефтяной трубы такого точно не вытянет.
aabzel Автор
Тогда РФ окончательно станет чьей-нибудь колонией
progchip666
Китайской? Процесс пошёл.
Javian
СССР и СЭВ многое просто копировали или на прямую покупали. Не так уж много надо военным.
progchip666
Копировать начали далеко не сразу. Когда "компьютеры были большими", стоили дорого и использовались для научных и статистических расчётов СССР был на уровне паритета. Потом компьютеры стали персональными и на западе они стали доступны даже частникам. Массовость стала быстро расти. А в СССР не было рынка - не было достаточного количества индивидуальных платёжеспособных пользователей из за перекосов ценообразования в том числе. Пришлось всё больше и больше копировать, а значит всё больше отставать...