/** * @brief Data receiving process thread * * This function is the thread for processing data receiving tasks. When * it wake up, it checks the receiving queue for processing the come in data. * If protocol is running out of buffer, as soon as it gets a free buffer, * it passes to driver for continuing the receiving. * * @param data The regular thread data. * @return None. */ static void *uart_rx_thread(void *data) { struct gb_operation *operation = NULL; struct gb_uart_receive_data_request *request = NULL; struct buf_node *node = NULL; struct gb_bundle *bundle = data; struct gb_uart_info *info = bundle->priv; struct device *dev = bundle->dev; int ret; while (1) { sem_wait(&info->rx_sem); if (info->thread_stop) { break; } node = get_node_from(&info->data_queue); if (node) { operation = gb_operation_create(info->cport, GB_UART_PROTOCOL_RECEIVE_DATA, sizeof(*request) + node->data_size); if (!operation) { uart_report_error(GB_UART_EVENT_PROTOCOL_ERROR, __func__); } else { request = gb_operation_get_request_payload(operation); request->size = cpu_to_le16(node->data_size); request->flags = node->data_flags; memcpy(request->data, node->buffer, node->data_size); ret = gb_operation_send_request(operation, NULL, false); if (ret) { uart_report_error(GB_UART_EVENT_PROTOCOL_ERROR, __func__); } gb_operation_destroy(operation); } put_node_back(&info->free_queue, node); } /* * In case there is no free node in callback. */ if (info->require_node) { node = get_node_from(&info->free_queue); info->rx_node = node; ret = device_uart_start_receiver(dev, node->buffer, info->rx_buf_size, NULL, NULL, uart_rx_callback); if (ret) { uart_report_error(GB_UART_EVENT_DEVICE_ERROR, __func__); } info->require_node = 0; } } return NULL; }
/** * @brief Modem and line status process thread * * This function is the thread for processing modem and line status change. It * uses the operation to send the event to the peer. It only sends the required * status for protocol, not the all status in UART. * * @param data The regular thread data. * @return None. */ static void *uart_status_thread(void *data) { uint16_t updated_status = 0; struct gb_uart_serial_state_request *request; struct gb_uart_info *info = data; int ret = 0; while (1) { sem_wait(&info->status_sem); if (info->thread_stop) { break; } updated_status = parse_ms_ls_registers(info->updated_ms, info->updated_ls); /* * Only send the status bits which protocol need to know to peer */ if (info->last_serial_state ^ updated_status) { info->last_serial_state = updated_status; request = gb_operation_get_request_payload(info->ms_ls_operation); request->control = updated_status; ret = gb_operation_send_request(info->ms_ls_operation, NULL, false); if (ret) { uart_report_error(GB_UART_EVENT_PROTOCOL_ERROR, __func__); } } } return NULL; }
/** * @brief Callback for data receiving * * The callback function provided to device driver for being notified when * driver received a data stream. * * This function Must be called from interrupt context. * * It put the current operation to received queue and gets another operation to * continue receiving. Then notifies rx thread to process. * * @param buffer Data buffer. * @param length Received data length. * @param error Error code when driver receiving. * @return None. */ static void uart_rx_callback(uint8_t *buffer, int length, int error) { struct op_node *node; int ret; *info->rx_node->data_size = cpu_to_le16(length); put_node_back(&info->data_queue, info->rx_node); /* notify rx thread to process this data*/ sem_post(&info->rx_sem); node = get_node_from(&info->free_queue); if (!node) { /* * there is no free buffer, inform the rx thread to engage another uart * receiver. */ info->require_node = 1; return; } info->rx_node = node; ret = device_uart_start_receiver(info->dev, node->buffer, info->rx_buf_size, NULL, NULL, uart_rx_callback); if (ret) { uart_report_error(GB_UART_EVENT_PROTOCOL_ERROR, __func__); } }
/** * @brief Data receiving process thread * * This function is the thread for processing data receiving tasks. When * it wake up, it checks the receiving queue for processing the come in data. * If protocol is running out of operation, once it gets a free operation, * it passes to driver for continuing the receiving. * * @param data The regular thread data. * @return None. */ static void *uart_rx_thread(void *data) { struct op_node *node = NULL; int ret; while (1) { sem_wait(&info->rx_sem); if (info->thread_stop) { break; } node = get_node_from(&info->data_queue); if (node) { ret = gb_operation_send_request(node->operation, NULL, false); if (ret) { uart_report_error(GB_UART_EVENT_PROTOCOL_ERROR, __func__); } put_node_back(&info->free_queue, node); } /* * In case there is no free node in callback. */ if (info->require_node) { node = get_node_from(&info->free_queue); info->rx_node = node; ret = device_uart_start_receiver(info->dev, node->buffer, info->rx_buf_size, NULL, NULL, uart_rx_callback); if (ret) { uart_report_error(GB_UART_EVENT_DEVICE_ERROR, __func__); } info->require_node = 0; } } return NULL; }
/** * @brief Callback for data receiving * * The callback function provided to device driver for being notified when * driver received a data stream. * * This function Must be called from interrupt context. * * It put the current buffer to received queue and gets another buffer to * continue receiving. Then notifies rx thread to process. * * @param dev Pointer to the UART device controller * @param data Pointer to struct gb_uart_info. * @param buffer Data buffer. * @param length Received data length. * @param error Error code when driver receiving. * @return None. */ static void uart_rx_callback(struct device *dev, void *data, uint8_t *buffer, int length, int error) { struct gb_uart_info *info; struct buf_node *node; int ret; uint8_t flags = 0; DEBUGASSERT(data); info = data; info->rx_node->data_size = length; if (error & LSR_OE) { flags |= GB_UART_RECV_FLAG_OVERRUN; } if (error & LSR_PE) { flags |= GB_UART_RECV_FLAG_PARITY; } if (error & LSR_FE) { flags |= GB_UART_RECV_FLAG_FRAMING; } if (error & LSR_BI) { flags |= GB_UART_RECV_FLAG_BREAK; } info->rx_node->data_flags = flags; put_node_back(&info->data_queue, info->rx_node); /* notify rx thread to process this data*/ sem_post(&info->rx_sem); node = get_node_from(&info->free_queue); if (!node) { /* * there is no free buffer, inform the rx thread to engage another uart * receiver. */ info->require_node = 1; return; } info->rx_node = node; ret = device_uart_start_receiver(dev, node->buffer, info->rx_buf_size, NULL, NULL, uart_rx_callback); if (ret) { uart_report_error(GB_UART_EVENT_PROTOCOL_ERROR, __func__); } }