app_mailbox.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include <stddef.h>
  13. #include <string.h>
  14. #include "app_mailbox.h"
  15. #include "nrf_error.h"
  16. #include "app_util_platform.h"
  17. #include "app_util.h"
  18. #include "nrf_assert.h"
  19. ret_code_t app_mailbox_create(const app_mailbox_t * queue_def)
  20. {
  21. queue_def->p_cb->r_idx = 0;
  22. queue_def->p_cb->w_idx = 0;
  23. queue_def->p_cb->len = 0;
  24. queue_def->p_cb->mode = APP_MAILBOX_MODE_NO_OVERFLOW;
  25. return NRF_SUCCESS;
  26. }
  27. static __INLINE void dequeue(app_mailbox_cb_t * p_cb, uint8_t queue_sz)
  28. {
  29. uint8_t r_idx = p_cb->r_idx + 1;
  30. p_cb->len--;
  31. //Handle index wrapping.
  32. p_cb->r_idx = (r_idx == queue_sz) ? 0 : r_idx;
  33. }
  34. static __INLINE void enqueue(app_mailbox_cb_t * p_cb, uint8_t queue_sz)
  35. {
  36. uint8_t w_idx = p_cb->w_idx + 1;
  37. p_cb->len++;
  38. //Handle index wrapping.
  39. p_cb->w_idx = (w_idx == queue_sz) ? 0 : w_idx;
  40. }
  41. ret_code_t app_mailbox_put(const app_mailbox_t * p_mailbox, void * p_item)
  42. {
  43. ASSERT(p_mailbox);
  44. return app_mailbox_sized_put(p_mailbox, p_item, p_mailbox->item_sz);
  45. }
  46. ret_code_t app_mailbox_sized_put(const app_mailbox_t * p_mailbox, void * p_item, uint16_t size)
  47. {
  48. ASSERT((uint32_t)p_item>0);
  49. ASSERT(p_mailbox);
  50. uint32_t err_code = NRF_ERROR_INTERNAL;
  51. uint32_t * p_dst = p_mailbox->p_pool;
  52. bool do_put = true;
  53. uint8_t queue_sz = p_mailbox->queue_sz;
  54. uint16_t item_sz = p_mailbox->item_sz;
  55. app_mailbox_cb_t * p_cb = p_mailbox->p_cb;
  56. CRITICAL_REGION_ENTER();
  57. if (p_cb->len == queue_sz)
  58. {
  59. if (p_cb->mode == APP_MAILBOX_MODE_NO_OVERFLOW)
  60. {
  61. do_put = false;
  62. }
  63. else
  64. {
  65. // Remove the oldest element.
  66. dequeue(p_cb, queue_sz);
  67. }
  68. err_code = NRF_ERROR_NO_MEM;
  69. }
  70. else
  71. {
  72. err_code = NRF_SUCCESS;
  73. }
  74. if (do_put)
  75. {
  76. p_dst = (uint32_t *)((uint32_t)p_dst + (p_cb->w_idx * (item_sz + sizeof(uint32_t))));
  77. enqueue(p_cb, queue_sz);
  78. //Put data in mailbox.
  79. *p_dst = (uint32_t)size;
  80. p_dst++;
  81. memcpy(p_dst, p_item, size);
  82. }
  83. CRITICAL_REGION_EXIT();
  84. return err_code;
  85. }
  86. ret_code_t app_mailbox_get(const app_mailbox_t * p_mailbox, void * p_item)
  87. {
  88. uint16_t size;
  89. return app_mailbox_sized_get(p_mailbox, p_item, &size);
  90. }
  91. ret_code_t app_mailbox_sized_get(const app_mailbox_t * p_mailbox, void * p_item, uint16_t * p_size)
  92. {
  93. ASSERT(p_mailbox);
  94. ASSERT((uint32_t)p_item>0);
  95. uint32_t * p_src = p_mailbox->p_pool;
  96. ret_code_t err_code = NRF_SUCCESS;
  97. uint16_t item_sz = p_mailbox->item_sz;
  98. uint8_t queue_sz = p_mailbox->queue_sz;
  99. app_mailbox_cb_t * p_cb = p_mailbox->p_cb;
  100. CRITICAL_REGION_ENTER();
  101. if (p_cb->len == 0)
  102. {
  103. err_code = NRF_ERROR_NO_MEM;
  104. }
  105. else
  106. {
  107. p_src = (void *)((uint32_t)p_src + (p_cb->r_idx * (item_sz + sizeof(uint32_t))));
  108. dequeue(p_cb, queue_sz);
  109. }
  110. if (err_code == NRF_SUCCESS)
  111. {
  112. uint16_t size = (uint16_t)*p_src;
  113. *p_size = size;
  114. p_src++;
  115. memcpy(p_item, p_src, size);
  116. }
  117. CRITICAL_REGION_EXIT();
  118. return err_code;
  119. }
  120. uint32_t app_mailbox_length_get (const app_mailbox_t * p_mailbox)
  121. {
  122. ASSERT(p_mailbox);
  123. return p_mailbox->p_cb->len;
  124. }
  125. void app_mailbox_mode_set(const app_mailbox_t * p_mailbox, app_mailbox_overflow_mode_t mode)
  126. {
  127. ASSERT(p_mailbox);
  128. p_mailbox->p_cb->mode = mode;
  129. }