Implement a secure ICS protocol targeting LoRa Node151 microcontroller for controlling irrigation.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 
 

340 satır
7.2 KiB

  1. /*-
  2. * Copyright 2021 John-Mark Gurney.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  14. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23. * SUCH DAMAGE.
  24. *
  25. */
  26. #include "stm32l1xx.h"
  27. #include "stm32l1xx_hal.h"
  28. /* LoRaMac headers */
  29. #include <board.h>
  30. #include <adc.h>
  31. #include <radio.h>
  32. #include <delay.h>
  33. /* lora-irr headers */
  34. #include <misc.h>
  35. #include <strobe_rng_init.h>
  36. #include <comms.h>
  37. enum {
  38. CMD_TERMINATE = 1,
  39. CMD_WAITFOR = 2,
  40. CMD_RUNFOR = 3,
  41. CMD_PING = 4,
  42. CMD_SETUNSET = 5,
  43. };
  44. /*
  45. * rxpktavail is initialized to true meaning that the data in rxpkt
  46. * can be over written. When a packet is received, the data is copied
  47. * to rxpkt, and then rxpktavail is set to false. Once the packet has
  48. * been processed, it is set back to true.
  49. */
  50. static uint8_t rxpkt[128];
  51. static struct pktbuf rxpktbuf;
  52. static volatile bool rxpktavail;
  53. static uint8_t shared_key[] = "foobar";
  54. static struct pktbuf shared_key_buf = (struct pktbuf){
  55. .pkt = shared_key,
  56. .pktlen = sizeof shared_key - 1,
  57. };
  58. static struct comms_state cs;
  59. void
  60. txdone(void)
  61. {
  62. /* restart Rx when Tx done */
  63. Radio.Rx(0);
  64. }
  65. void
  66. txtimeout(void)
  67. {
  68. /* restart Rx when Tx done */
  69. Radio.Rx(0);
  70. }
  71. void
  72. rxdone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
  73. {
  74. if (rxpktavail) {
  75. memcpy(rxpkt, payload, MIN(sizeof rxpkt, size));
  76. rxpktbuf = (struct pktbuf){
  77. .pkt = rxpkt,
  78. .pktlen = size,
  79. };
  80. rxpktavail = false;
  81. }
  82. }
  83. void
  84. rxtimeout(void)
  85. {
  86. }
  87. void
  88. rxerr(void)
  89. {
  90. }
  91. RadioEvents_t revents = {
  92. .TxDone = txdone,
  93. .TxTimeout = txtimeout,
  94. .RxDone = rxdone,
  95. .RxTimeout = rxtimeout,
  96. .RxError = rxerr,
  97. };
  98. /*
  99. * Seed the randomness from the radio. This is not a great
  100. * seed, and is hard to gauge how much randomness is really
  101. * there. Assuming about 1 bit per 8 bits looks pretty safe,
  102. * so add 256 * 8 / 32 words.
  103. */
  104. static void
  105. radio_seed_rng(void)
  106. {
  107. #if 0
  108. uint32_t v;
  109. int i;
  110. for (i = 0; i < 256 * 8 / 32; i++) {
  111. v = Radio.Random();
  112. strobe_seed_prng((uint8_t *)&v, sizeof v);
  113. }
  114. #endif
  115. }
  116. static void
  117. analog_seed_rng(void)
  118. {
  119. #if 1
  120. uint16_t v;
  121. int i;
  122. for (i = 0; i < 256 / 2; i++) {
  123. /*
  124. * Capture some ADC data. If pin is floating, 0xfff
  125. * happens frequently, if pin is grounded, 0 happens
  126. * frequently, filter these values out.
  127. */
  128. do {
  129. v = AdcReadChannel(&Adc, ADC_CHANNEL_21);
  130. } while (v == 0 || v == 0xfff);
  131. strobe_seed_prng((uint8_t *)&v, sizeof v);
  132. }
  133. #endif
  134. }
  135. static inline uint32_t
  136. letoh_32(uint8_t *v)
  137. {
  138. return v[0] | (v[1] << 8) | (v[2] << 16) | (v[3] << 24);
  139. }
  140. struct chaninfo {
  141. GPIO_TypeDef *bank;
  142. uint16_t pinnum;
  143. bool init;
  144. } chans[] = {
  145. [0] = { .bank = GPIOB, .pinnum = GPIO_PIN_5, .init = true, },
  146. [1] = { .bank = GPIOB, .pinnum = GPIO_PIN_6, .init = true, },
  147. [2] = { .bank = GPIOB, .pinnum = GPIO_PIN_7, .init = true, },
  148. [3] = { .bank = GPIOB, .pinnum = GPIO_PIN_9, .init = true, },
  149. [4] = { .bank = GPIOB, .pinnum = GPIO_PIN_8, .init = true, },
  150. };
  151. #define nitems(x) (sizeof(x) / sizeof *(x))
  152. static void
  153. set_chan(uint32_t chan, bool val)
  154. {
  155. struct chaninfo ci;
  156. if (chan < nitems(chans)) {
  157. ci = chans[chan];
  158. HAL_GPIO_WritePin(ci.bank, ci.pinnum, val ? GPIO_PIN_SET : GPIO_PIN_RESET);
  159. }
  160. }
  161. static void
  162. setup_gpio()
  163. {
  164. GPIO_InitTypeDef GPIO_InitStruct;
  165. int i;
  166. for (i = 0; i < nitems(chans); i++) {
  167. GPIO_InitStruct = (GPIO_InitTypeDef){
  168. .Pin = chans[i].pinnum,
  169. .Mode = GPIO_MODE_OUTPUT_PP,
  170. .Pull = GPIO_NOPULL,
  171. .Speed = GPIO_SPEED_FREQ_LOW,
  172. };
  173. HAL_GPIO_Init(chans[i].bank, &GPIO_InitStruct);
  174. set_chan(i, chans[i].init);
  175. }
  176. }
  177. void
  178. procmsg(struct pktbuf inbuf, struct pktbuf *outbuf)
  179. {
  180. uint32_t args[5];
  181. int i, apos;
  182. i = 1;
  183. apos = 0;
  184. while (i < inbuf.pktlen) {
  185. if (i + 4 <= inbuf.pktlen) {
  186. args[apos++] = letoh_32(&inbuf.pkt[i]);
  187. i += 4;
  188. }
  189. }
  190. outbuf->pkt[0] = inbuf.pkt[0];
  191. switch (inbuf.pkt[0]) {
  192. case CMD_SETUNSET:
  193. if (apos == 2)
  194. set_chan(args[0], args[1]);
  195. break;
  196. default:
  197. outbuf->pkt[0] = 0;
  198. break;
  199. }
  200. outbuf->pktlen = 1;
  201. }
  202. int
  203. main()
  204. {
  205. strobe_rng_init();
  206. BoardInitMcu();
  207. Radio.Init(&revents);
  208. analog_seed_rng();
  209. radio_seed_rng();
  210. strobe_rng_save();
  211. setup_gpio();
  212. /* turn on LED */
  213. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
  214. Radio.SetModem(MODEM_LORA);
  215. Radio.SetChannel(914350 * 1000);
  216. /* RX/TX parameters */
  217. const uint8_t modem = MODEM_LORA;
  218. const uint8_t bandwidth = 0 /* 128 kHz */;
  219. const uint8_t datarate = 7 /* 128 chips */;
  220. const uint8_t coderate = 1 /* 4/5 */;
  221. const uint8_t preambleLen = 4 /* symbols */;
  222. const uint8_t fixLen = 0 /* variable */;
  223. const uint8_t crcOn = 1 /* on */;
  224. const uint8_t freqHopOn = 0 /* off */;
  225. const bool iqInverted = false /* not inverted */;
  226. Radio.SetRxConfig(modem, bandwidth, datarate, coderate, 0/*afc*/,
  227. preambleLen, 5/*symTimeout*/, fixLen, 0/*payloadlen*/, crcOn,
  228. freqHopOn, 0/*hopPeriod*/, iqInverted, true/*rxcont*/);
  229. Radio.SetTxConfig(modem, 11/*power*/, 0/*fdev*/, bandwidth, datarate,
  230. coderate, preambleLen, fixLen, crcOn, freqHopOn, 0/*hopPeriod*/,
  231. iqInverted, 1000/*timeout*/);
  232. /* blink led */
  233. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
  234. DelayMs(300);
  235. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
  236. Radio.Rx(0);
  237. comms_init(&cs, procmsg, &shared_key_buf);
  238. uint8_t txbuf[128] = "i'mhere";
  239. struct pktbuf txpktbuf;
  240. txpktbuf = (struct pktbuf){
  241. .pkt = txbuf,
  242. .pktlen = 8,
  243. };
  244. Radio.Send(txpktbuf.pkt, txpktbuf.pktlen);
  245. rxpktavail = true;
  246. //Radio.Rx(0);
  247. loop:
  248. BoardLowPowerHandler();
  249. if (Radio.IrqProcess != NULL)
  250. Radio.IrqProcess();
  251. if (!rxpktavail) {
  252. txpktbuf = (struct pktbuf){
  253. .pkt = txbuf,
  254. .pktlen = sizeof txbuf,
  255. };
  256. /* process available packet */
  257. comms_process(&cs, rxpktbuf, &txpktbuf);
  258. rxpktavail = true;
  259. if (txpktbuf.pktlen) {
  260. int i;
  261. for (i = 0; i < 1; i++) {
  262. DelayMs(20);
  263. Radio.Send(txpktbuf.pkt, txpktbuf.pktlen);
  264. }
  265. #if 0
  266. /* blink led */
  267. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
  268. DelayMs(300);
  269. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
  270. DelayMs(300);
  271. #endif
  272. }
  273. #if 0
  274. /* blink led */
  275. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
  276. DelayMs(300);
  277. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
  278. #endif
  279. }
  280. goto loop;
  281. }