📄 hostif_low.c
字号:
if (mode == HOSTIF_TX_MSGCMDEVAL) { /* Use a special buffer shared with the hostifReceiveBlock function */ /* with the MsgCmdEval already formatted by the hostifReceiveBlock() */ hostifSendPacket(hostif_msg_cmd_eval_buf, 5); /* Since this is an error condition, we ignore the eventual Ack sent by the Host */ /* no ACK timer needed */ return TL_inprogress; } if (hostif_app_buffer_length < hostifCommProtocolParam.maxI2CFrameSize + 2) { /* Application command fits in a single LL frame, do not start a Transport session */ hostifSendPacket(hostif_app_buffer, hostif_app_buffer_length); /* no ACK timer needed */ return TL_inprogress; } else { ASSERT(FALSE, "Message longer than I2C frame in SendBlock"); } return TL_ready;}/******************************************************************************//* Function: hostifRecvBlock *//* *//*! \brief Host communication protocol Link Layer Rx function. * \param[in] packet Pointer to the caller-provided data buffer * \param[in] len Length of the data contained in the buffer * \return void * \remark Transport Layer receive function. * Performs reassembly of the packets into a message Block * and processes the BlockID and PacketNumber fields from * the Block header if necessary. * In the current implementation it is assumed that only * messages that fit in a LL frame are sent from the Host. *//******************************************************************************/void hostifRecvBlock(char *msgp, uint16 *blockLenp){ switch (hostifRecvPacket(msgp, blockLenp)) { case LL_checksumError: /* Create MsgCmdEval with Checksum error */ createMsgCmdEval(&hostif_msg_cmd_eval_buf[0], CMDE_CHECK_SUM_ERROR, *msgp, *(msgp+1)); send_hostif_inevent(HOSTIF_SEND_MSGCMDEVAL); break; case LL_badSize: /* Create MsgCmdEval with Checksum error */ createMsgCmdEval(&hostif_msg_cmd_eval_buf[0], CMDE_LENGTH_ERROR, *msgp, *(msgp+1)); send_hostif_inevent(HOSTIF_SEND_MSGCMDEVAL); break; case LL_ok: /* We received a complete Command/Message, no more processing required */ //JS added MsgCommandEval(NoError) createMsgCmdEval(&hostif_msg_cmd_eval_buf[0], CMDE_NO_ERROR, *msgp, *(msgp+1)); send_hostif_inevent(HOSTIF_SEND_MSGCMDEVAL); break; }}/******************************************************************************//* Function: hostifSendPacket *//* *//*! \brief Host communication protocol Link Layer Tx function. * \param[in] packet Pointer to the caller-provided data buffer * \param[in] len Length of the data contained in the buffer * \return void * \remark Adds the L (length) and CS (checksum) bytes to the * message and passes it to the low level tx functions. * Example: * Original message * D1 D2 D3 .. Dn * Message passed to low level driver * L D1 D2 D3 .. Dn CS * Details: * Copies the data from the caller buffer to the I2C IRQ buffer. * The function also processes the Ack Failure condition by * retransmitting the errored message after 100ms. During this * period, all tx to the Host are buffered but not sent. *//******************************************************************************/void hostifSendPacket(char *packet, uint16 len){ char *i2c_buf; uint16 checksum; ASSERT((len+2 <= DEFAULT_MAX_I2C_FRAME_SIZE), "Requested transmission longer than I2C frame"); ASSERT((i2c_flags.tx_msg_done == 1), "I2C LinkLayer tx buffer full"); if (len > DEFAULT_MAX_I2C_FRAME_SIZE - 2) { /* truncate the message, not nice but preserve sanity over the I2C */ len = DEFAULT_MAX_I2C_FRAME_SIZE - 2; } /* Copy the local buffer to the buffer used by the IRQ routine */ /* which does the actual transmission */ i2c_buf = &i2c_irq_tx_buffer[0]; /* First transmitted byte is the length, include the CS in the count */ *i2c_buf++ = len + 1; // L byte /* Calculate the checksum while copying message to IRQ buffer */ /* do not include the L byte in the checksum calculation */ checksum = 0x5a; while (len-- > 0) { checksum += (uint16) *packet; *i2c_buf++ = *packet++; } /* Append the checksum */ *i2c_buf = (char) (checksum & 0xFF); /* Use this flag to avoid overwriting the tx buffer: */ /* The IRQ will set it to 1 after sending this message */ i2c_flags.tx_msg_done = 0; /* No need to set the buffer length anywhere, it is the I2C master */ /* that decides when to stop reception. */ /* The I2C master uses the first transmitted byte (L) as packet length. */ /* Bring down the CRQ line to signal to the master that we have a message ready */ /* Will be reset to high in the IRQ after the first byte transmission */ PDB &= I2C_CRQ_AND_MASK; start_timer(HOSTIF_LL_CRQ_TIMER, HOSTIF_LL_CRQ_TIMER_DURATION);}/******************************************************************************//* Function: hostifRecvPacket *//* *//*! \brief Host communication protocol Link Layer receive function. * \param[in] packet Pointer to the caller-provided data buffer * \param[in] len Length of the data contained in the buffer * \return LLStatusType * \remark Removes the L (length) and CS (checksum) bytes to the * message and passes it to the upper level rx functions. * Performs che checksum check. * Example: * Original message * L D1 D2 D3 .. Dn CS * Message passed to the caller * D1 D2 D3 .. Dn *//******************************************************************/LLStatusType hostifRecvPacket(char *user_packet, uint16 *len){ uint16 irq_len, checksum; char *irq_packet; /* If this assertion fails we may have overwritten outside the irq msg buffer */ ASSERT(i2c_irq_rx_buffer_idx < DEFAULT_MAX_I2C_FRAME_SIZE, "Illegal message size in hostifRecvPacket"); /* L byte: add 1 because L does not count the L byte itself */ irq_len = i2c_irq_rx_buffer[0] + 1; /* Sanity check: the L field should be coherent with the */ /* packet length reported by the physical layer */ if (i2c_irq_rx_buffer_idx != irq_len) { return LL_badSize; } /* Copy message to caller buffer and calculate checksum */ irq_packet = &i2c_irq_rx_buffer[1]; /* Skip the L byte */ /* Do not copy the CS and the L bytes */ irq_len -= 2; /* Save length for caller */ *len = irq_len; checksum = 0x5a; while (irq_len-- > 0) { checksum += (uint16) *irq_packet; *user_packet++ = *irq_packet++; } /* Signal to IRQ that the rx buffer is free */ i2c_flags.i2c_new_cmd = 0; if ((checksum & 0xFF) != *irq_packet) { *len = 0; return LL_checksumError; } return LL_ok; }/******************************************************************************//* Function: fifo_reset *//* *//*! \brief Initialize a message FIFO * \param[in] fifo pointer the message FIFO * \return void * \remark *//******************************************************************/void fifo_reset(t_hostif_msg_fifo *fifo){ uint16 i; char *bufp; fifo->readp = fifo->writep = &(fifo->circular_buffer[0]); fifo->top = fifo->readp + HOSTIF_MSG_FIFO_LEN; /* for debug only */ bufp = &(fifo->circular_buffer[0]); for (i = 0; i < HOSTIF_MSG_FIFO_LEN; i++) { *bufp++ = 0; } }/******************************************************************************//* Function: fifo_has_msg *//* *//*! \brief Check if there are messaged in the FIFO * \param[in] fifo pointer the message FIFO * \return t_bool * \remark *//******************************************************************/t_bool fifo_has_msg(t_hostif_msg_fifo *fifo){ if (fifo->readp == fifo->writep) { return FALSE; } else { return TRUE; }}/******************************************************************************//* Function: fifo_push_msg *//* *//*! \brief Push one message into the message FIFO * \param[in] fifo pointer to the message FIFO * \param[in] msg pointer to message to push on the FIFO * \return t_bool * \remark Each message is prepended in the FIFO with its * length (1 byte). *//******************************************************************/t_bool fifo_push_msg(t_hostif_msg_fifo *fifo, char* msg, uint16 msg_len){ sint16 free_cells; // [RB] was uint16, but some overflow condition goes undetected in that case sint16 pointer_diff; semaphore_wait(&sem_hostif_critical); pointer_diff = fifo->writep - fifo->readp; if (pointer_diff < 0) { free_cells = -pointer_diff - 1; } else { free_cells = HOSTIF_MSG_FIFO_LEN - pointer_diff - 1; } /* Add one to store the length byte also */ if (free_cells < msg_len + 1) { semaphore_signal(&sem_hostif_critical); return FALSE; } /* Use only one byte for the length of the message for now */ /* Might extend in the future to two bytes */ ASSERT((msg_len < 256), "Message too long in fifo_push_msg"); *(fifo->writep)++ = (char) msg_len; while (msg_len-- > 0) { if (fifo->writep == fifo->top) { fifo->writep = fifo->circular_buffer; } *(fifo->writep)++ = *msg++; } if (fifo->writep == fifo->top) { fifo->writep = fifo->circular_buffer; } semaphore_signal(&sem_hostif_critical); return TRUE;}/******************************************************************************//* Function: fifo_pop_msg *//* *//*! \brief Pop one msg from the message FIFO * \param[in] fifo pointer to the message FIFO * \param[in] ch charachter popped from the FIFO * \return t_bool * \remark *//******************************************************************/t_bool fifo_pop_msg(t_hostif_msg_fifo *fifo, char *msg, uint16 *msg_len){ uint16 local_len; semaphore_wait(&sem_hostif_critical); if (fifo->writep == fifo->readp) { semaphore_signal(&sem_hostif_critical); return FALSE; } local_len = *(fifo->readp)++; *msg_len = local_len; while (local_len-- > 0) { if (fifo->readp == fifo->top) { fifo->readp = fifo->circular_buffer; } *msg++ = *(fifo->readp)++; } if (fifo->readp == fifo->top) { fifo->readp = fifo->circular_buffer; } semaphore_signal(&sem_hostif_critical); return TRUE;}#if (0 != HAVE_POSITION)/******************************************************************************//* Function: hostif_calculate_checksum *//* *//*! \brief Calculate checksum of the last position memory * \return void * \remark *//******************************************************************/uint32 hostif_calculate_checksum(void){ uint16 i = sizeof (hostifStoredValueType); uint32 checksum = 0; while(i --) { checksum += hostifStoredData.f.all[i]; } return checksum;}/******************************************************************************//* Function: hostif_verify_checksum *//* *//*! \brief Verify checksum of the last position memory * \return void * \remark *//******************************************************************/uint8 hostif_verify_checksum(void){ return (hostif_calculate_checksum() == hostifStoredData.Checksum);}/******************************************************************************//* Function: hostif_update_checksum *//* *//*! \brief Update checksum of the last position memory * \return void * \remark *//******************************************************************/void hostif_update_checksum(void){ hostifStoredData.Checksum = hostif_calculate_checksum();}#endif /* HAVE_POSITION */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -