LoRaMacConfirmQueue.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. / _____) _ | |
  3. ( (____ _____ ____ _| |_ _____ ____| |__
  4. \____ \| ___ | (_ _) ___ |/ ___) _ \
  5. _____) ) ____| | | || |_| ____( (___| | | |
  6. (______/|_____)_|_|_| \__)_____)\____)_| |_|
  7. (C)2013 Semtech
  8. ___ _____ _ ___ _ _____ ___ ___ ___ ___
  9. / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
  10. \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
  11. |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
  12. embedded.connectivity.solutions===============
  13. Description: LoRa MAC confirm queue implementation
  14. License: Revised BSD License, see LICENSE.TXT file include in the project
  15. Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
  16. */
  17. #include <stdint.h>
  18. #include <stdbool.h>
  19. #include <stddef.h>
  20. #include "lora-radio-timer.h"
  21. #include "utilities.h"
  22. #include "LoRaMac.h"
  23. #include "LoRaMacConfirmQueue.h"
  24. /*
  25. * LoRaMac Confirm Queue Context NVM structure
  26. */
  27. typedef struct sLoRaMacConfirmQueueNvmCtx
  28. {
  29. /*!
  30. * MlmeConfirm queue data structure
  31. */
  32. MlmeConfirmQueue_t MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN];
  33. /*!
  34. * Counts the number of MlmeConfirms to process
  35. */
  36. uint8_t MlmeConfirmQueueCnt;
  37. /*!
  38. * Variable which holds a common status
  39. */
  40. LoRaMacEventInfoStatus_t CommonStatus;
  41. } LoRaMacConfirmQueueNvmCtx_t;
  42. /*
  43. * LoRaMac Confirm Queue Context structure
  44. */
  45. typedef struct sLoRaMacConfirmQueueCtx
  46. {
  47. /*!
  48. * LoRaMac callback function primitives
  49. */
  50. LoRaMacPrimitives_t* Primitives;
  51. /*!
  52. * Pointer to the first element of the ring buffer
  53. */
  54. MlmeConfirmQueue_t* BufferStart;
  55. /*!
  56. * Pointer to the last element of the ring buffer
  57. */
  58. MlmeConfirmQueue_t* BufferEnd;
  59. /*
  60. * Callback function to notify the upper layer about context change
  61. */
  62. LoRaMacConfirmQueueNvmEvent LoRaMacConfirmQueueNvmEvent;
  63. /*!
  64. * Non-volatile module context.
  65. */
  66. LoRaMacConfirmQueueNvmCtx_t* ConfirmQueueNvmCtx;
  67. } LoRaMacConfirmQueueCtx_t;
  68. /*
  69. * Non-volatile module context.
  70. */
  71. static LoRaMacConfirmQueueNvmCtx_t ConfirmQueueNvmCtx;
  72. /*
  73. * Module context.
  74. */
  75. static LoRaMacConfirmQueueCtx_t ConfirmQueueCtx;
  76. static MlmeConfirmQueue_t* IncreaseBufferPointer( MlmeConfirmQueue_t* bufferPointer )
  77. {
  78. if( bufferPointer == &ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN - 1] )
  79. {
  80. // Reset to the first element
  81. bufferPointer = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue;
  82. }
  83. else
  84. {
  85. // Increase
  86. bufferPointer++;
  87. }
  88. return bufferPointer;
  89. }
  90. static MlmeConfirmQueue_t* DecreaseBufferPointer( MlmeConfirmQueue_t* bufferPointer )
  91. {
  92. if( bufferPointer == ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue )
  93. {
  94. // Reset to the last element
  95. bufferPointer = &ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN - 1];
  96. }
  97. else
  98. {
  99. bufferPointer--;
  100. }
  101. return bufferPointer;
  102. }
  103. static MlmeConfirmQueue_t* GetElement( Mlme_t request, MlmeConfirmQueue_t* bufferStart, MlmeConfirmQueue_t* bufferEnd )
  104. {
  105. MlmeConfirmQueue_t* element = bufferStart;
  106. while( element != bufferEnd )
  107. {
  108. if( element->Request == request )
  109. {
  110. // We have found the element
  111. return element;
  112. }
  113. else
  114. {
  115. element = IncreaseBufferPointer( element );
  116. }
  117. }
  118. return NULL;
  119. }
  120. void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, LoRaMacConfirmQueueNvmEvent confirmQueueNvmCtxChanged )
  121. {
  122. ConfirmQueueCtx.Primitives = primitives;
  123. // Assign nvm context
  124. ConfirmQueueCtx.ConfirmQueueNvmCtx = &ConfirmQueueNvmCtx;
  125. // Init counter
  126. ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt = 0;
  127. // Init buffer
  128. ConfirmQueueCtx.BufferStart = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue;
  129. ConfirmQueueCtx.BufferEnd = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue;
  130. memset1( ( uint8_t* )ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue, 0xFF, sizeof( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue ) );
  131. // Common status
  132. ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = LORAMAC_EVENT_INFO_STATUS_ERROR;
  133. // Assign callback
  134. ConfirmQueueCtx.LoRaMacConfirmQueueNvmEvent = confirmQueueNvmCtxChanged;
  135. }
  136. bool LoRaMacConfirmQueueRestoreNvmCtx( void* confirmQueueNvmCtx )
  137. {
  138. // Restore module context
  139. if( confirmQueueNvmCtx != NULL )
  140. {
  141. memcpy1( ( uint8_t* )&ConfirmQueueNvmCtx, ( uint8_t* ) confirmQueueNvmCtx, sizeof( ConfirmQueueNvmCtx ) );
  142. return true;
  143. }
  144. else
  145. {
  146. return false;
  147. }
  148. }
  149. void* LoRaMacConfirmQueueGetNvmCtx( size_t* confirmQueueNvmCtxSize )
  150. {
  151. *confirmQueueNvmCtxSize = sizeof( ConfirmQueueNvmCtx );
  152. return &ConfirmQueueNvmCtx;
  153. }
  154. bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm )
  155. {
  156. if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
  157. {
  158. // Protect the buffer against overwrites
  159. return false;
  160. }
  161. // Add the element to the ring buffer
  162. ConfirmQueueCtx.BufferEnd->Request = mlmeConfirm->Request;
  163. ConfirmQueueCtx.BufferEnd->Status = mlmeConfirm->Status;
  164. ConfirmQueueCtx.BufferEnd->RestrictCommonReadyToHandle = mlmeConfirm->RestrictCommonReadyToHandle;
  165. ConfirmQueueCtx.BufferEnd->ReadyToHandle = false;
  166. // Increase counter
  167. ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt++;
  168. // Update end pointer
  169. ConfirmQueueCtx.BufferEnd = IncreaseBufferPointer( ConfirmQueueCtx.BufferEnd );
  170. return true;
  171. }
  172. bool LoRaMacConfirmQueueRemoveLast( void )
  173. {
  174. if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt == 0 )
  175. {
  176. return false;
  177. }
  178. // Increase counter
  179. ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt--;
  180. // Update start pointer
  181. ConfirmQueueCtx.BufferEnd = DecreaseBufferPointer( ConfirmQueueCtx.BufferEnd );
  182. return true;
  183. }
  184. bool LoRaMacConfirmQueueRemoveFirst( void )
  185. {
  186. if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt == 0 )
  187. {
  188. return false;
  189. }
  190. // Increase counter
  191. ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt--;
  192. // Update start pointer
  193. ConfirmQueueCtx.BufferStart = IncreaseBufferPointer( ConfirmQueueCtx.BufferStart );
  194. return true;
  195. }
  196. void LoRaMacConfirmQueueSetStatus( LoRaMacEventInfoStatus_t status, Mlme_t request )
  197. {
  198. MlmeConfirmQueue_t* element = NULL;
  199. if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
  200. {
  201. element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
  202. if( element != NULL )
  203. {
  204. element->Status = status;
  205. element->ReadyToHandle = true;
  206. }
  207. }
  208. }
  209. LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatus( Mlme_t request )
  210. {
  211. MlmeConfirmQueue_t* element = NULL;
  212. if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
  213. {
  214. element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
  215. if( element != NULL )
  216. {
  217. return element->Status;
  218. }
  219. }
  220. return LORAMAC_EVENT_INFO_STATUS_ERROR;
  221. }
  222. void LoRaMacConfirmQueueSetStatusCmn( LoRaMacEventInfoStatus_t status )
  223. {
  224. MlmeConfirmQueue_t* element = ConfirmQueueCtx.BufferStart;
  225. ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = status;
  226. if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
  227. {
  228. do
  229. {
  230. element->Status = status;
  231. // Set the status if it is allowed to set it with a call to
  232. // LoRaMacConfirmQueueSetStatusCmn.
  233. if( element->RestrictCommonReadyToHandle == false )
  234. {
  235. element->ReadyToHandle = true;
  236. }
  237. element = IncreaseBufferPointer( element );
  238. }while( element != ConfirmQueueCtx.BufferEnd );
  239. }
  240. }
  241. LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatusCmn( void )
  242. {
  243. return ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus;
  244. }
  245. bool LoRaMacConfirmQueueIsCmdActive( Mlme_t request )
  246. {
  247. if( GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd ) != NULL )
  248. {
  249. return true;
  250. }
  251. return false;
  252. }
  253. void LoRaMacConfirmQueueHandleCb( MlmeConfirm_t* mlmeConfirm )
  254. {
  255. uint8_t nbElements = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt;
  256. bool readyToHandle = false;
  257. MlmeConfirmQueue_t mlmeConfirmToStore;
  258. for( uint8_t i = 0; i < nbElements; i++ )
  259. {
  260. mlmeConfirm->MlmeRequest = ConfirmQueueCtx.BufferStart->Request;
  261. mlmeConfirm->Status = ConfirmQueueCtx.BufferStart->Status;
  262. readyToHandle = ConfirmQueueCtx.BufferStart->ReadyToHandle;
  263. if( readyToHandle == true )
  264. {
  265. ConfirmQueueCtx.Primitives->MacMlmeConfirm( mlmeConfirm );
  266. }
  267. else
  268. {
  269. // The request is not processed yet. Store the state.
  270. mlmeConfirmToStore.Request = ConfirmQueueCtx.BufferStart->Request;
  271. mlmeConfirmToStore.Status = ConfirmQueueCtx.BufferStart->Status;
  272. mlmeConfirmToStore.RestrictCommonReadyToHandle = ConfirmQueueCtx.BufferStart->RestrictCommonReadyToHandle;
  273. }
  274. // Increase the pointer afterwards to prevent overwrites
  275. LoRaMacConfirmQueueRemoveFirst( );
  276. if( readyToHandle == false )
  277. {
  278. // Add a request which has not been finished again to the queue
  279. LoRaMacConfirmQueueAdd( &mlmeConfirmToStore );
  280. }
  281. }
  282. }
  283. uint8_t LoRaMacConfirmQueueGetCnt( void )
  284. {
  285. return ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt;
  286. }
  287. bool LoRaMacConfirmQueueIsFull( void )
  288. {
  289. if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
  290. {
  291. return true;
  292. }
  293. else
  294. {
  295. return false;
  296. }
  297. }