/** * \brief Sent byte to UART. * * \param chn Communication channel [0, 1] * \param data Data to sent * * \retval Number of characters sent */ uint16_t buart_if_tx_char(uint8_t chn, char data) { return (buart_if_write(chn, &data, 1)); }
/** * \brief Encodes the escape characters and transmits the message * * \param uc_port_idx Port to transmit through * \param msg Pointer to data to be transmitted * * * \return Result of operation: USI_OK: Sent * USI_STATUS_TX_FAILED: Not sent */ static usi_status_t _usi_encode_and_send(uint8_t uc_port_idx, cmd_params_t *msg) { uint32_t ul_crc; uint8_t *puc_tx_buf; uint8_t *puc_aux_tx_buf; uint8_t uc_cmd; uint32_t ul_idx_in_orig; uint32_t ul_idx_aux = 0; uint16_t us_put_chars = 0; uint8_t uc_delimiter = MSGMARK; uint8_t uc_escape = ESCMARK; uint8_t uc_escaped_byte = 0; uint8_t *puc_next_token = NULL; uint8_t *puc_aux_next_token = NULL; uint32_t ul_size_coded = 0; uint8_t uc_p_type = msg->uc_p_type; uint16_t us_len_token = 0; uint16_t us_len = msg->us_len; uint16_t us_sent_chars; /* Get ptr to TxBuffer */ puc_tx_buf = usi_cfg_tx_buf[uc_port_idx].puc_buf; puc_aux_tx_buf = usi_cfg_aux_tx_buf->puc_buf; /* Copy message to aux buffer including header */ puc_aux_tx_buf[0] = LEN_HI_PROTOCOL(us_len); puc_aux_tx_buf[1] = LEN_LO_PROTOCOL(us_len) + TYPE_PROTOCOL(uc_p_type); memcpy(&puc_aux_tx_buf[2], msg->puc_buf, us_len); /* Adjust XLEN if uc_p_type is internal protocol */ uc_cmd = puc_aux_tx_buf[CMD_PROTOCOL_OFFSET]; if ((uc_p_type == PROTOCOL_432_PRIME) || (uc_p_type == PROTOCOL_MAC_PRIME)) { puc_aux_tx_buf[CMD_PROTOCOL_OFFSET] = LEN_EX_PROTOCOL(us_len) + CMD_PROTOCOL(uc_cmd); } /* Add 2 header bytes to LEN */ us_len += 2; /* Calculate CRC */ switch (uc_p_type) { case MNGP_PRIME_GETQRY: case MNGP_PRIME_GETRSP: case MNGP_PRIME_SET: case MNGP_PRIME_RESET: case MNGP_PRIME_REBOOT: case MNGP_PRIME_FU: case MNGP_PRIME_EN_PIBQRY: case MNGP_PRIME_EN_PIBRSP: ul_crc = pcrc_calculate_prime_crc(puc_aux_tx_buf, us_len, PCRC_HT_USI, PCRC_CRC_TYPE_32); puc_aux_tx_buf[us_len] = (uint8_t)(ul_crc >> 24); puc_aux_tx_buf[us_len + 1] = (uint8_t)(ul_crc >> 16); puc_aux_tx_buf[us_len + 2] = (uint8_t)(ul_crc >> 8); puc_aux_tx_buf[us_len + 3] = (uint8_t)ul_crc; us_len += 4; break; case PROTOCOL_SNIF_PRIME: case PROTOCOL_BASEMNG_PRIME: case PROTOCOL_PRIME_SERIAL: case PROTOCOL_ATPL230: case PROTOCOL_USER_DEFINED: ul_crc = pcrc_calculate_prime_crc(puc_aux_tx_buf, us_len, PCRC_HT_USI, PCRC_CRC_TYPE_16); puc_aux_tx_buf[us_len] = (uint8_t)(ul_crc >> 8); puc_aux_tx_buf[us_len + 1] = (uint8_t)(ul_crc); us_len += 2; break; case PROTOCOL_MAC_PRIME: case PROTOCOL_MLME_PRIME: case PROTOCOL_PLME_PRIME: case PROTOCOL_432_PRIME: case PROTOCOL_INTERNAL: default: ul_crc = pcrc_calculate_prime_crc(puc_aux_tx_buf, us_len, PCRC_HT_USI, PCRC_CRC_TYPE_8); puc_aux_tx_buf[us_len] = (uint8_t)(ul_crc); us_len += 1; break; } /* Fill tx buffer adding required escapes */ ul_idx_in_orig = usi_cfg_param[uc_port_idx].us_idx_in; ul_size_coded = us_len + 2 /* for MSGMARKs */; /* Check if there is still room */ if (ul_idx_in_orig + ul_size_coded > usi_cfg_tx_buf[uc_port_idx].us_size) { /* No Room. Return error */ return USI_STATUS_TX_BUFFER_OVERFLOW; } /* Start Escape */ puc_tx_buf[usi_cfg_param[uc_port_idx].us_idx_in++] = MSGMARK; us_put_chars++; while (us_len) { /* Look for the next MSGMARK present within the data */ puc_next_token = memchr(&puc_aux_tx_buf[ul_idx_aux], uc_delimiter, us_len); if (puc_next_token == NULL) { /* MSGMARK not found -> look for the next ESCMARK * present within the data */ puc_next_token = memchr(&puc_aux_tx_buf[ul_idx_aux], uc_escape, us_len); if (puc_next_token != NULL) { uc_escaped_byte = ESC_ESCMARK; } } else { /* Check if there is an ESCMARK before the MSGMARK */ puc_aux_next_token = memchr(&puc_aux_tx_buf[ul_idx_aux], uc_escape, puc_next_token - &puc_aux_tx_buf[ul_idx_aux]); if (puc_aux_next_token != NULL) { uc_escaped_byte = ESC_ESCMARK; puc_next_token = puc_aux_next_token; } else { uc_escaped_byte = ESC_MSGMARK; } } /* Perform the codification of the MSGMARK or the ESCMARK */ if (puc_next_token != NULL) { ul_size_coded++; /* Check if there is still room */ if (ul_idx_in_orig + ul_size_coded > usi_cfg_tx_buf[uc_port_idx].us_size) { /* No Room. Reset index and return error */ return USI_STATUS_TX_BUFFER_OVERFLOW; } us_len_token = puc_next_token - &puc_aux_tx_buf[ul_idx_aux]; /* Copy the part without special bytes into the tx buf */ memcpy(&puc_tx_buf[usi_cfg_param[uc_port_idx].us_idx_in], &puc_aux_tx_buf[ul_idx_aux], us_len_token); us_len -= us_len_token + 1; ul_idx_aux += us_len_token + 1; usi_cfg_param[uc_port_idx].us_idx_in += us_len_token; /* Encode the special character */ puc_tx_buf[usi_cfg_param[uc_port_idx].us_idx_in++] = ESCMARK; puc_tx_buf[usi_cfg_param[uc_port_idx].us_idx_in++] = uc_escaped_byte; us_put_chars += us_len_token + 2; } else { memcpy(&puc_tx_buf[usi_cfg_param[uc_port_idx].us_idx_in], &puc_aux_tx_buf[ul_idx_aux], us_len); usi_cfg_param[uc_port_idx].us_idx_in += us_len; us_put_chars += us_len; us_len = 0; } } puc_tx_buf[usi_cfg_param[uc_port_idx].us_idx_in++] = MSGMARK; us_put_chars++; /* Message ready to be sent */ us_len = usi_cfg_param[uc_port_idx].us_idx_in; /* Check if there is something to transmit */ if (usi_cfg_param[uc_port_idx].us_tx_block_timer == 0) { while (usi_cfg_param[uc_port_idx].us_idx_in) { /* Send chars to device, checking how many have been really processed by device */ if (usi_cfg_map_ports[uc_port_idx].uc_s_type == UART_TYPE) { us_sent_chars = buart_if_write(usi_cfg_map_ports[uc_port_idx].uc_chn, usi_cfg_tx_buf[uc_port_idx].puc_buf, us_len); } else if (usi_cfg_map_ports[uc_port_idx].uc_s_type == USART_TYPE) { us_sent_chars = busart_if_write(usi_cfg_map_ports[uc_port_idx].uc_chn, usi_cfg_tx_buf[uc_port_idx].puc_buf, us_len); } else { us_sent_chars = us_len; /* Port wrongly mapped */ } if (us_sent_chars > 0) { /* Adjust buffer values depending on sent chars */ usi_cfg_param[uc_port_idx].us_idx_in -= us_sent_chars; } else { /* USI_ERROR: UART/USART error */ return USI_STATUS_UART_ERROR; } } } else { /* USI_ERROR: TX blocked */ return USI_STATUS_TX_BLOCKED; } return USI_STATUS_OK; }