knx
ETS configurable knx-stack
cc1310_platform.cpp
Go to the documentation of this file.
1 #ifdef DeviceFamily_CC13X0
2 
3 #include <cstdio>
4 #include <cstdarg>
5 #include <cstring>
6 #include <cmath>
7 
8 #include <ti/devices/DeviceFamily.h>
9 #include DeviceFamily_constructPath(driverlib/sys_ctrl.h)
10 #include <ti/drivers/GPIO.h>
11 
12 #include "SEGGER_RTT.h"
13 
14 #include "Board.h"
15 
16 #include "knx/bits.h"
17 #include "cc1310_platform.h"
18 
19 //#define printf(args...) (SEGGER_RTT_printf(0, args))
20 //#define PRINT_RTT
21 #define PRINT_UART
22 
23 static uint8_t serialNumber[6];
24 // KNX_FLASH_SIZE shall be defined in CMakeLists.txt for example. It is also used in class Memory in memory.cpp
25 static uint8_t NVS_buffer[KNX_FLASH_SIZE];
26 
27 static UART_Handle uart;
28 
29 static NVS_Handle nvsHandle;
30 
31 static ClockP_Handle clk0Handle;
32 static ClockP_Struct clk0Struct;
33 static volatile uint32_t msCounter = 0;
34 
35 static void clk0Fxn(uintptr_t arg0)
36 {
37  msCounter++;
38 }
39 
40 static void setupClock()
41 {
42  ClockP_Params clkParams;
43  ClockP_Params_init(&clkParams);
44  clkParams.period = 1000 / ClockP_tickPeriod;
45  clkParams.startFlag = true;
46  ClockP_construct(&clk0Struct, (ClockP_Fxn)clk0Fxn, 1000 / ClockP_tickPeriod, &clkParams);
47  clk0Handle = ClockP_handle(&clk0Struct);
48 }
49 
50 static void setupGPIO()
51 {
52  /* Configure the LED and button pins */
53  GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
54  GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
55  GPIO_setConfig(Board_GPIO_BUTTON0, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
56  GPIO_setConfig(Board_GPIO_BUTTON1, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
57 }
58 
59 static void setupUART()
60 {
61  UART_Params uartParams;
62  UART_Params_init(&uartParams);
63  uartParams.writeDataMode = UART_DATA_BINARY;
64  uartParams.readDataMode = UART_DATA_BINARY;
65  uartParams.readReturnMode = UART_RETURN_FULL;
66  uartParams.readEcho = UART_ECHO_OFF;
67  uartParams.baudRate = 115200;
68  uart = UART_open(Board_UART0, &uartParams);
69 
70  if (uart == NULL)
71  {
72  while (true)
73  {}
74  }
75 }
76 
77 static void setupNVS()
78 {
79  NVS_Params nvsParams;
80  NVS_Params_init(&nvsParams);
81  nvsHandle = NVS_open(Board_NVSINTERNAL, &nvsParams);
82 
83  if (nvsHandle == NULL)
84  {
85  println("NVS_open() failed.");
86  return;
87  }
88 
89  NVS_Attrs attrs;
90  NVS_getAttrs(nvsHandle, &attrs);
91  print("NVS flash size: ");
92  println((int)attrs.regionSize);
93  print("NVS flash sector size: ");
94  println((int)attrs.sectorSize);
95 
96  if (GPIO_read(Board_GPIO_BUTTON1) == 0)
97  {
98  println("Button1 is pressed. Erasing flash...");
99  int_fast16_t result = NVS_erase(nvsHandle, 0, attrs.regionSize);
100 
101  if (result != NVS_STATUS_SUCCESS)
102  {
103  print("Error erasing NVS, result: ");
104  println(result);
105  }
106  else
107  {
108  println("NVS successfully erased.");
109  }
110  }
111 }
112 
113 void sleep(uint32_t sec)
114 {
115  ClockP_sleep(sec);
116 }
117 
118 void usleep(uint32_t usec)
119 {
120  ClockP_usleep(usec);
121 }
122 
123 uint32_t millis()
124 {
125  // 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
126  //return Clock_getTicks() * (uint64_t) Clock_tickPeriod / 1000; // rtos
127  //return ClockP_getTicks( * (uint64_t) Clock_tickPeriod / 1000); //nortos
128  return msCounter;
129 }
130 
131 void delay(uint32_t ms)
132 {
133  ClockP_usleep(ms * 1000);
134  //sleep(ms * (1000 / ClockP_tickPeriod)); //rtos
135  //sleepTicks(millis * 1000ULL / ClockP_tickPeriod); //nortos
136 }
137 
138 void delayMicroseconds (unsigned int howLong)
139 {
140  ClockP_usleep(howLong);
141 }
142 
143 #ifndef KNX_NO_PRINT
144 size_t write(uint8_t c)
145 {
146 #if defined(PRINT_UART)
147  uint8_t buffer[1] = {c};
148  return UART_write(uart, buffer, sizeof(buffer));
149 #elif defined (PRINT_RTT)
150  return SEGGER_RTT_PutChar(0, (char)c);
151 #else
152  return 1;
153 #endif
154 }
155 
156 #if 0
157 size_t write(const uint8_t* buffer, size_t size)
158 {
159  size_t n = 0;
160 
161  while (size--)
162  {
163  if (write(*buffer++))
164  {
165  n++;
166  }
167  else
168  {
169  break;
170  }
171  }
172 
173  return n;
174 }
175 #else
176 size_t write(const uint8_t* buffer, size_t size)
177 {
178 #if defined(PRINT_UART)
179  return UART_write(uart, buffer, size);
180 #elif defined (PRINT_RTT)
181  return SEGGER_RTT_Write(0, buffer, size);
182 #else
183  return size;
184 #endif
185 }
186 #endif
187 
188 size_t write(const char* buffer, size_t size)
189 {
190  return write((const uint8_t*)buffer, size);
191 }
192 
193 void print(const char* s)
194 {
195  if (s == NULL)
196  {
197  return;
198  }
199 
200  write(s, strlen(s));
201 }
202 void print(char c)
203 {
204  write(c);
205 }
206 
207 void printUint64(uint64_t value, int base = DEC)
208 {
209  char buf[8 * sizeof(uint64_t) + 1];
210  char* str = &buf[sizeof(buf) - 1];
211  *str = '\0';
212 
213  uint64_t n = value;
214 
215  do
216  {
217  char c = n % base;
218  n /= base;
219 
220  *--str = c < 10 ? c + '0' : c + 'A' - 10;
221  } while (n > 0);
222 
223  print(str);
224 }
225 
226 void print(long long num, int base)
227 {
228  if (base == 0)
229  {
230  write(num);
231  return;
232  }
233  else if (base == 10)
234  {
235  if (num < 0)
236  {
237  print('-');
238  num = -num;
239  printUint64(num, 10);
240  return;
241  }
242 
243  printUint64(num, 10);
244  return;
245  }
246  else
247  {
248  printUint64(num, base);
249  return;
250  }
251 }
252 
253 void print(unsigned long long num, int base)
254 {
255  if (base == 0)
256  {
257  write(num);
258  return;
259  }
260  else
261  {
262  printUint64(num, base);
263  return;
264  }
265 }
266 
267 void print(unsigned char num, int base)
268 {
269  print((unsigned long long)num, base);
270 }
271 
272 void print(int num, int base)
273 {
274  print((long long)num, base);
275 }
276 
277 void print(unsigned int num, int base)
278 {
279  print((unsigned long long)num, base);
280 }
281 
282 void print(long num, int base)
283 {
284  print((long long)num, base);
285 }
286 
287 void print(unsigned long num, int base)
288 {
289  print((unsigned long long)num, base);
290 }
291 
292 void printFloat(double number, uint8_t digits)
293 {
294  if (std::isnan(number))
295  {
296  print("nan");
297  return;
298  }
299 
300  if (std::isinf(number))
301  {
302  print("inf");
303  return;
304  }
305 
306  if (number > 4294967040.0)
307  {
308  print("ovf"); // constant determined empirically
309  return;
310  }
311 
312  if (number < -4294967040.0)
313  {
314  print("ovf"); // constant determined empirically
315  return;
316  }
317 
318  // Handle negative numbers
319  if (number < 0.0)
320  {
321  print('-');
322  number = -number;
323  }
324 
325  // Round correctly so that print(1.999, 2) prints as "2.00"
326  double rounding = 0.5;
327 
328  for (uint8_t i = 0; i < digits; ++i)
329  rounding /= 10.0;
330 
331  number += rounding;
332 
333  // Extract the integer part of the number and print it
334  unsigned long int_part = (unsigned long)number;
335  double remainder = number - (double)int_part;
336  printUint64(int_part);
337 
338  // Print the decimal point, but only if there are digits beyond
339  if (digits > 0)
340  {
341  print('.');
342  }
343 
344  // Extract digits from the remainder one at a time
345  while (digits-- > 0)
346  {
347  remainder *= 10.0;
348  unsigned int toPrint = (unsigned int)(remainder);
349  printUint64(toPrint);
350  remainder -= toPrint;
351  }
352 }
353 
354 void print(double num, int digits = 2)
355 {
356  printFloat(num, digits);
357 }
358 
359 void println(void)
360 {
361  print("\r\n");
362 }
363 
364 void println(const char* s)
365 {
366  print(s);
367  println();
368 }
369 void println(char c)
370 {
371  print(c);
372  println();
373 }
374 
375 void println(unsigned char num, int base)
376 {
377  print(num, base);
378  println();
379 }
380 
381 void println(int num, int base)
382 {
383  print(num, base);
384  println();
385 }
386 
387 void println(unsigned int num, int base)
388 {
389  print(num, base);
390  println();
391 }
392 
393 void println(long num, int base)
394 {
395  print(num, base);
396  println();
397 }
398 
399 void println(unsigned long num, int base)
400 {
401  print(num, base);
402  println();
403 }
404 
405 void println(unsigned long long num, int base)
406 {
407  printUint64(num, base);
408  println();
409 }
410 
411 void println(double num, int digits = 2)
412 {
413  print(num, digits);
414  println();
415 }
416 
417 void println(double num)
418 {
419  // default: print 10 digits
420  println(num, 10);
421 }
422 #endif // KNX_NO_PRINT
423 
424 uint32_t digitalRead(uint32_t dwPin)
425 {
426  print("ignoring digitalRead: pin: ");
427  print(dwPin);
428  println(", returning 0");
429  return 0;
430 }
431 
432 void digitalWrite(unsigned long pin, unsigned long value)
433 {
434  if (pin == Board_GPIO_LED0)
435  {
436  if (value > 0)
437  {
438  GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
439  }
440  else
441  {
442  GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF);
443  }
444  }
445  else
446  {
447  print("dummy digitalWrite: pin: ");
448  print(pin);
449  print(", value: ");
450  println(value, HEX);
451  }
452 }
453 
454 void pinMode(unsigned long pin, unsigned long mode)
455 {
456  print("ignoring pinMode: pin: ");
457  print(pin);
458  print(", mode: ");
459  println(mode, HEX);
460 }
461 
462 typedef void (*IsrFuncPtr)();
463 static IsrFuncPtr gpioCallback;
464 static void gpioButtonFxn0(uint_least8_t index)
465 {
466  gpioCallback();
467 }
468 
469 void attachInterrupt(uint32_t pin, IsrFuncPtr callback, uint32_t mode)
470 {
471  if (pin == Board_GPIO_BUTTON0)
472  {
473  gpioCallback = callback;
474  /* install Button callback */
475  GPIO_setCallback(Board_GPIO_BUTTON0, gpioButtonFxn0);
476 
477  /* Enable interrupts */
478  GPIO_enableInt(Board_GPIO_BUTTON0);
479  }
480  else
481  {
482  print("dummy attachInterrupt: pin: ");
483  print(pin);
484  print(", mode: ");
485  println(mode, HEX);
486  }
487 }
488 
490 {
491  // build serialNumber from IEEE MAC Address (MAC is 8 bytes, serialNumber 6 bytes only)
492  *(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
493 }
494 
496 {
497 }
498 
500 {
501  // TI Drivers init
502  // According to SDK docs it is safe to call them AFTER NoRTOS_Start()
503  // If RTOS is used and multiple thread use the same driver, then the init shall be performed before BIOS_Start()
504  GPIO_init();
505  UART_init();
506  NVS_init();
507 
508  // Init GPIO
509  setupGPIO();
510 
511  // Init UART
512  setupUART();
513 
514  // tick Period on this controller 10us so we use our own millisecond clock
515  setupClock();
516 
517  // Init flash
518  setupNVS();
519 }
520 
521 uint8_t* CC1310Platform::getEepromBuffer(uint32_t size)
522 {
523  if (size > KNX_FLASH_SIZE)
524  {
525  fatalError();
526  }
527 
528  NVS_read(nvsHandle, 0, (void*) NVS_buffer, size);
529 
530  for (int i = 0; i < size; i++)
531  {
532  if (NVS_buffer[i] != 0)
533  {
534  return NVS_buffer;
535  }
536  }
537 
538  memset(NVS_buffer, 0xff, size);
539 
540  return NVS_buffer;
541 }
542 
544 {
545  println("CC1310Platform::commitToEeprom() ...");
546 
547  int_fast16_t result = NVS_write(nvsHandle, 0, (void*)NVS_buffer, KNX_FLASH_SIZE, NVS_WRITE_ERASE | NVS_WRITE_POST_VERIFY);
548 
549  if (result != NVS_STATUS_SUCCESS)
550  {
551  print("Error writing to NVS, result: ");
552  println(result);
553  }
554  else
555  {
556  println("NVS successfully written");
557  }
558 
559  delay(500);
560 }
561 
563 {
564  println("System restart in 500ms.");
565  delay(500);
566  SysCtrlSystemReset();
567  // Should neber be reached!
568  fatalError();
569 }
570 
572 {
573  println("A fatal error occured. Stopped.");
574 
575  while (true)
576  {
577  /* Turn on user LED */
578  GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF);
579  GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);
580  delay(500);
581  GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
582  GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_OFF);
583  delay(500);
584  }
585 }
586 
587 #endif // DeviceFamily_CC13X0
void printUint64(uint64_t value, int base=DEC)
void pinMode(unsigned long pin, unsigned long mode)
void attachInterrupt(uint32_t pin, IsrFuncPtr callback, uint32_t mode)
size_t write(uint8_t c)
void print(const char *s)
void digitalWrite(unsigned long pin, unsigned long value)
void delay(uint32_t ms)
void(* IsrFuncPtr)()
void usleep(uint32_t usec)
void sleep(uint32_t sec)
void println(void)
uint32_t millis()
void delayMicroseconds(unsigned int howLong)
uint32_t digitalRead(uint32_t dwPin)
void printFloat(double number, uint8_t digits)
void restart() final
void commitToEeprom() final
void fatalError() final
uint8_t * getEepromBuffer(uint32_t size) final
virtual ~CC1310Platform()