/** * Searched a statically assigned array for a free entry * Starts with the last given element + 1 for optimisation * This call is safe from both ISR and task context * @return poiter to a free csp_packet_t or NULL if out of memory */ void * csp_buffer_get(size_t buf_size) { void * buffer; CSP_ENTER_CRITICAL(csp_critical_lock); buffer = csp_buffer_get_isr(buf_size); CSP_EXIT_CRITICAL(csp_critical_lock); return buffer; }
/** pbuf_cleanup * Purge all packets buffers that have timed out */ static void pbuf_cleanup(void) { int i; pbuf_element_t *buf; /* Lock packet buffer */ CSP_ENTER_CRITICAL(pbuf_sem); /* Loop through buffer elements */ for (i = 0; i < PBUF_ELEMENTS; i++) { buf = &pbuf[i]; if (buf->state == BUF_USED) { /* Check timeout */ uint32_t now = csp_get_ms(); if (now - buf->last_used > PBUF_TIMEOUT_MS) { csp_log_info("CAN Buffer element timed out\r\n"); /* Reuse packet buffer */ pbuf_free(buf, NULL); } } } /* Unlock packet buffer */ CSP_EXIT_CRITICAL(pbuf_sem); }
/** pbuf_find * Find matching packet buffer or create a new one. * @param id CFP identifier to match * @param mask Match mask * @return Pointer to matching or new packet buffer element on success, NULL on error. */ static pbuf_element_t *pbuf_find(uint32_t id, uint32_t mask, CSP_BASE_TYPE *task_woken) { /* Search for matching buffer */ int i; pbuf_element_t *buf, *ret = NULL; /* Lock packet buffer */ if (task_woken == NULL) CSP_ENTER_CRITICAL(pbuf_sem); /* Loop through buffer elements */ for (i = 0; i < PBUF_ELEMENTS; i++) { buf = &pbuf[i]; if((buf->state == BUF_USED) && ((buf->cfpid & mask) == (id & mask))) { pbuf_timestamp(buf, task_woken); ret = buf; break; } } /* Unlock packet buffer */ if (task_woken == NULL) CSP_EXIT_CRITICAL(pbuf_sem); /* No matching buffer was found */ return ret; }
/** pbuf_new * Get new packet buffer element. * @param id CFP identifier * @return Pointer to packet buffer element on success, NULL on error. */ static pbuf_element_t *pbuf_new(uint32_t id, CSP_BASE_TYPE *task_woken) { /* Search for free buffer */ int i; pbuf_element_t *buf, *ret = NULL; /* Lock packet buffer */ if (task_woken == NULL) CSP_ENTER_CRITICAL(pbuf_sem); /* Loop through buffer elements */ for (i = 0; i < PBUF_ELEMENTS; i++) { buf = &pbuf[i]; if(buf->state == BUF_FREE) { buf->state = BUF_USED; buf->cfpid = id; buf->remain = 0; pbuf_timestamp(buf, task_woken); ret = buf; break; } } /* Unlock packet buffer */ if (task_woken == NULL) CSP_EXIT_CRITICAL(pbuf_sem); /* No free buffer was found */ return ret; }
/** pbuf_free * Free buffer element and associated CSP packet buffer element. * @param buf Buffer element to free * @param free_packet true if the associated packet should be freed as well * @return 0 on success, -1 on error. */ static int pbuf_free(pbuf_element_t *buf, CSP_BASE_TYPE *task_woken, bool free_packet) { int ret; /* Lock packet buffer */ if (task_woken == NULL) CSP_ENTER_CRITICAL(pbuf_sem); ret = pbuf_free_locked(buf, task_woken, free_packet); /* Unlock packet buffer */ if (task_woken == NULL) CSP_EXIT_CRITICAL(pbuf_sem); return ret; }
/** pbuf_free * Free buffer element and associated CSP packet buffer element. * @param buf Buffer element to free * @return 0 on success, -1 on error. */ static int pbuf_free(pbuf_element_t *buf, CSP_BASE_TYPE *task_woken) { int32_t refcount; /* Lock packet buffer */ if (task_woken == NULL) CSP_ENTER_CRITICAL(pbuf_sem); /* Free CSP packet */ if (buf->packet != NULL) { /* first check to see if the buffer was already free. This could happen if the top level timeout occurred already. If so, no need to free it again */ refcount = csp_buffer_get_refcount(buf->packet); if (refcount > 0) { if (task_woken == NULL) { csp_buffer_free(buf->packet); } else { csp_buffer_free_isr(buf->packet); } } buf->packet = NULL; } /* Mark buffer element free */ buf->state = BUF_FREE; buf->rx_count = 0; buf->tx_count = 0; buf->cfpid = 0; buf->last_used = 0; buf->remain = 0; /* Unlock packet buffer */ if (task_woken == NULL) CSP_EXIT_CRITICAL(pbuf_sem); return CSP_ERR_NONE; }