#ifdef DeviceFamily_CC13X0 #include #include #include #include #include #include DeviceFamily_constructPath(driverlib/sys_ctrl.h) #include #include "SEGGER_RTT.h" #include "Board.h" #include "knx/bits.h" #include "cc1310_platform.h" //#define printf(args...) (SEGGER_RTT_printf(0, args)) //#define PRINT_RTT #define PRINT_UART static uint8_t serialNumber[6]; // KNX_FLASH_SIZE shall be defined in CMakeLists.txt for example. It is also used in class Memory in memory.cpp static uint8_t NVS_buffer[KNX_FLASH_SIZE]; static UART_Handle uart; static NVS_Handle nvsHandle; static ClockP_Handle clk0Handle; static ClockP_Struct clk0Struct; static volatile uint32_t msCounter = 0; static void clk0Fxn(uintptr_t arg0) { msCounter++; } static void setupClock() { ClockP_Params clkParams; ClockP_Params_init(&clkParams); clkParams.period = 1000 / ClockP_tickPeriod; clkParams.startFlag = true; ClockP_construct(&clk0Struct, (ClockP_Fxn)clk0Fxn, 1000 / ClockP_tickPeriod, &clkParams); clk0Handle = ClockP_handle(&clk0Struct); } static void setupGPIO() { /* Configure the LED and button pins */ GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); GPIO_setConfig(Board_GPIO_BUTTON0, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING); GPIO_setConfig(Board_GPIO_BUTTON1, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING); } static void setupUART() { UART_Params uartParams; UART_Params_init(&uartParams); uartParams.writeDataMode = UART_DATA_BINARY; uartParams.readDataMode = UART_DATA_BINARY; uartParams.readReturnMode = UART_RETURN_FULL; uartParams.readEcho = UART_ECHO_OFF; uartParams.baudRate = 115200; uart = UART_open(Board_UART0, &uartParams); if (uart == NULL) { while (true) {} } } static void setupNVS() { NVS_Params nvsParams; NVS_Params_init(&nvsParams); nvsHandle = NVS_open(Board_NVSINTERNAL, &nvsParams); if (nvsHandle == NULL) { println("NVS_open() failed."); return; } NVS_Attrs attrs; NVS_getAttrs(nvsHandle, &attrs); print("NVS flash size: "); println((int)attrs.regionSize); print("NVS flash sector size: "); println((int)attrs.sectorSize); if (GPIO_read(Board_GPIO_BUTTON1) == 0) { println("Button1 is pressed. Erasing flash..."); int_fast16_t result = NVS_erase(nvsHandle, 0, attrs.regionSize); if (result != NVS_STATUS_SUCCESS) { print("Error erasing NVS, result: "); println(result); } else { println("NVS successfully erased."); } } } void sleep(uint32_t sec) { ClockP_sleep(sec); } void usleep(uint32_t usec) { ClockP_usleep(usec); } uint32_t millis() { // we use our own ms clock because the Os tick counter has counts 10us ticks and following calculation would not wrap correctly at 32bit boundary //return Clock_getTicks() * (uint64_t) Clock_tickPeriod / 1000; // rtos //return ClockP_getTicks( * (uint64_t) Clock_tickPeriod / 1000); //nortos return msCounter; } void delay(uint32_t ms) { ClockP_usleep(ms * 1000); //sleep(ms * (1000 / ClockP_tickPeriod)); //rtos //sleepTicks(millis * 1000ULL / ClockP_tickPeriod); //nortos } void delayMicroseconds (unsigned int howLong) { ClockP_usleep(howLong); } #ifndef KNX_NO_PRINT size_t write(uint8_t c) { #if defined(PRINT_UART) uint8_t buffer[1] = {c}; return UART_write(uart, buffer, sizeof(buffer)); #elif defined (PRINT_RTT) return SEGGER_RTT_PutChar(0, (char)c); #else return 1; #endif } #if 0 size_t write(const uint8_t* buffer, size_t size) { size_t n = 0; while (size--) { if (write(*buffer++)) { n++; } else { break; } } return n; } #else size_t write(const uint8_t* buffer, size_t size) { #if defined(PRINT_UART) return UART_write(uart, buffer, size); #elif defined (PRINT_RTT) return SEGGER_RTT_Write(0, buffer, size); #else return size; #endif } #endif size_t write(const char* buffer, size_t size) { return write((const uint8_t*)buffer, size); } void print(const char* s) { if (s == NULL) { return; } write(s, strlen(s)); } void print(char c) { write(c); } void printUint64(uint64_t value, int base = DEC) { char buf[8 * sizeof(uint64_t) + 1]; char* str = &buf[sizeof(buf) - 1]; *str = '\0'; uint64_t n = value; do { char c = n % base; n /= base; *--str = c < 10 ? c + '0' : c + 'A' - 10; } while (n > 0); print(str); } void print(long long num, int base) { if (base == 0) { write(num); return; } else if (base == 10) { if (num < 0) { print('-'); num = -num; printUint64(num, 10); return; } printUint64(num, 10); return; } else { printUint64(num, base); return; } } void print(unsigned long long num, int base) { if (base == 0) { write(num); return; } else { printUint64(num, base); return; } } void print(unsigned char num, int base) { print((unsigned long long)num, base); } void print(int num, int base) { print((long long)num, base); } void print(unsigned int num, int base) { print((unsigned long long)num, base); } void print(long num, int base) { print((long long)num, base); } void print(unsigned long num, int base) { print((unsigned long long)num, base); } void printFloat(double number, uint8_t digits) { if (std::isnan(number)) { print("nan"); return; } if (std::isinf(number)) { print("inf"); return; } if (number > 4294967040.0) { print("ovf"); // constant determined empirically return; } if (number < -4294967040.0) { print("ovf"); // constant determined empirically return; } // Handle negative numbers if (number < 0.0) { print('-'); number = -number; } // Round correctly so that print(1.999, 2) prints as "2.00" double rounding = 0.5; for (uint8_t i = 0; i < digits; ++i) rounding /= 10.0; number += rounding; // Extract the integer part of the number and print it unsigned long int_part = (unsigned long)number; double remainder = number - (double)int_part; printUint64(int_part); // Print the decimal point, but only if there are digits beyond if (digits > 0) { print('.'); } // Extract digits from the remainder one at a time while (digits-- > 0) { remainder *= 10.0; unsigned int toPrint = (unsigned int)(remainder); printUint64(toPrint); remainder -= toPrint; } } void print(double num, int digits = 2) { printFloat(num, digits); } void println(void) { print("\r\n"); } void println(const char* s) { print(s); println(); } void println(char c) { print(c); println(); } void println(unsigned char num, int base) { print(num, base); println(); } void println(int num, int base) { print(num, base); println(); } void println(unsigned int num, int base) { print(num, base); println(); } void println(long num, int base) { print(num, base); println(); } void println(unsigned long num, int base) { print(num, base); println(); } void println(unsigned long long num, int base) { printUint64(num, base); println(); } void println(double num, int digits = 2) { print(num, digits); println(); } void println(double num) { // default: print 10 digits println(num, 10); } #endif // KNX_NO_PRINT uint32_t digitalRead(uint32_t dwPin) { print("ignoring digitalRead: pin: "); print(dwPin); println(", returning 0"); return 0; } void digitalWrite(unsigned long pin, unsigned long value) { if (pin == Board_GPIO_LED0) { if (value > 0) { GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON); } else { GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF); } } else { print("dummy digitalWrite: pin: "); print(pin); print(", value: "); println(value, HEX); } } void pinMode(unsigned long pin, unsigned long mode) { print("ignoring pinMode: pin: "); print(pin); print(", mode: "); println(mode, HEX); } typedef void (*IsrFuncPtr)(); static IsrFuncPtr gpioCallback; static void gpioButtonFxn0(uint_least8_t index) { gpioCallback(); } void attachInterrupt(uint32_t pin, IsrFuncPtr callback, uint32_t mode) { if (pin == Board_GPIO_BUTTON0) { gpioCallback = callback; /* install Button callback */ GPIO_setCallback(Board_GPIO_BUTTON0, gpioButtonFxn0); /* Enable interrupts */ GPIO_enableInt(Board_GPIO_BUTTON0); } else { print("dummy attachInterrupt: pin: "); print(pin); print(", mode: "); println(mode, HEX); } } CC1310Platform::CC1310Platform() { // build serialNumber from IEEE MAC Address (MAC is 8 bytes, serialNumber 6 bytes only) *(uint32_t*)(serialNumber + 2) = HWREG(FCFG1_BASE + FCFG1_O_MAC_15_4_0) ^ HWREG(FCFG1_BASE + FCFG1_O_MAC_15_4_1); // make a 6 byte hash from 8 bytes } CC1310Platform::~CC1310Platform() { } void CC1310Platform::init() { // TI Drivers init // According to SDK docs it is safe to call them AFTER NoRTOS_Start() // If RTOS is used and multiple thread use the same driver, then the init shall be performed before BIOS_Start() GPIO_init(); UART_init(); NVS_init(); // Init GPIO setupGPIO(); // Init UART setupUART(); // tick Period on this controller 10us so we use our own millisecond clock setupClock(); // Init flash setupNVS(); } uint8_t* CC1310Platform::getEepromBuffer(uint32_t size) { if (size > KNX_FLASH_SIZE) { fatalError(); } NVS_read(nvsHandle, 0, (void*) NVS_buffer, size); for (int i = 0; i < size; i++) { if (NVS_buffer[i] != 0) { return NVS_buffer; } } memset(NVS_buffer, 0xff, size); return NVS_buffer; } void CC1310Platform::commitToEeprom() { println("CC1310Platform::commitToEeprom() ..."); int_fast16_t result = NVS_write(nvsHandle, 0, (void*)NVS_buffer, KNX_FLASH_SIZE, NVS_WRITE_ERASE | NVS_WRITE_POST_VERIFY); if (result != NVS_STATUS_SUCCESS) { print("Error writing to NVS, result: "); println(result); } else { println("NVS successfully written"); } delay(500); } void CC1310Platform::restart() { println("System restart in 500ms."); delay(500); SysCtrlSystemReset(); // Should neber be reached! fatalError(); } void CC1310Platform::fatalError() { println("A fatal error occured. Stopped."); while (true) { /* Turn on user LED */ GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF); GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON); delay(500); GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON); GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_OFF); delay(500); } } #endif // DeviceFamily_CC13X0