Beispiel #1
0
/**
 * \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));
}
Beispiel #2
0
/**
 * \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;
}