Ejemplo n.º 1
0
uint8_t atsha204Class::sha204c_wakeup(uint8_t *response)
{
    uint8_t ret_code = sha204p_wakeup();
    if (ret_code != SHA204_SUCCESS)
        return ret_code;

    ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response);
    if (ret_code != SHA204_SUCCESS)
        return ret_code;

    // Verify status response.
    Serial.print("Buffer pos: ");
    Serial.println(response[SHA204_BUFFER_POS_COUNT]);
    if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN)
        ret_code = SHA204_INVALID_SIZE;
    else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP)
        ret_code = SHA204_COMM_FAIL;
    else
    {
        if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33)
                || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43))
            ret_code = SHA204_BAD_CRC;
    }
    if (ret_code != SHA204_SUCCESS)
        delay(SHA204_COMMAND_EXEC_MAX);

    return ret_code;
}
Ejemplo n.º 2
0
/** \brief This function re-synchronizes communication.
 *
  Re-synchronizing communication is done in a maximum of five
  steps listed below. This function implements the first three steps.
  Since steps 4 and 5 (sending a Wake-up token and reading the
  response) are the same for TWI and SWI, they are implemented
  in the communication layer (#sha204c_resync).\n
  If the chip is not busy when the system sends a transmit flag,
  the chip should respond within t_turnaround. If t_exec has not
  already passed, the chip may be busy and the system should poll or
  wait until the maximum tEXEC time has elapsed. If the chip still
  does not respond to a second transmit flag within t_turnaround,
  it may be out of synchronization. At this point the system may
  take the following steps to reestablish communication:
  <ol>
     <li>Wait t_timeout.</li>
     <li>Send the transmit flag.</li>
     <li>
       If the chip responds within t_turnaround,
       then the system may proceed with more commands.
     </li>
     <li>Send a Wake token, wait t_whi, and send the transmit flag.</li>
     <li>
       The chip should respond with a 0x11 return status within
       t_turnaround, after which the system may proceed with more commands.
     </li>
   </ol>

 * \param[in] size size of rx buffer
 * \param[out] response pointer to response buffer
 * \return status of the operation
 */
uint8_t sha204p_resync(uint8_t size, uint8_t *response)
{
  delay_ms(SHA204_SYNC_TIMEOUT);
  return sha204p_receive_response(size, response);
}
Ejemplo n.º 3
0
uint8_t atsha204Class::sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout)
{
    uint8_t ret_code = SHA204_FUNC_FAIL;
    uint8_t ret_code_resync;
    uint8_t n_retries_send;
    uint8_t n_retries_receive;
    uint8_t i;
    uint8_t status_byte;
    uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT];
    uint8_t count_minus_crc = count - SHA204_CRC_SIZE;
    uint16_t execution_timeout_us = (uint16_t)(execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT;
    volatile uint16_t timeout_countdown;

    // Append CRC.
    sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc);

    // Retry loop for sending a command and receiving a response.
    n_retries_send = SHA204_RETRY_COUNT + 1;

    while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS))
    {
        // Send command.
        ret_code = sha204p_send_command(count, tx_buffer);
        if (ret_code != SHA204_SUCCESS)
        {
            if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE)
                return ret_code; // The device seems to be dead in the water.
            else
                continue;
        }

        // Wait minimum command execution time and then start polling for a response.
        delay(execution_delay);

        // Retry loop for receiving a response.
        n_retries_receive = SHA204_RETRY_COUNT + 1;
        while (n_retries_receive-- > 0)
        {
            // Reset response buffer.
            for (i = 0; i < rx_size; i++)
                rx_buffer[i] = 0;

            // Poll for response.
            timeout_countdown = execution_timeout_us;
            do
            {
                ret_code = sha204p_receive_response(rx_size, rx_buffer);
                timeout_countdown -= SHA204_RESPONSE_TIMEOUT;
            } while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE));

            if (ret_code == SHA204_RX_NO_RESPONSE)
            {
                // We did not receive a response. Re-synchronize and send command again.
                if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE)
                    // The device seems to be dead in the water.
                    return ret_code;
                else
                    break;
            }

            // Check whether we received a valid response.
            if (ret_code == SHA204_INVALID_SIZE)
            {
                // We see 0xFF for the count when communication got out of sync.
                ret_code_resync = sha204c_resync(rx_size, rx_buffer);
                if (ret_code_resync == SHA204_SUCCESS)
                    // We did not have to wake up the device. Try receiving response again.
                    continue;
                if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP)
                    // We could re-synchronize, but only after waking up the device.
                    // Re-send command.
                    break;
                else
                    // We failed to re-synchronize.
                    return ret_code;
            }

            // We received a response of valid size.
            // Check the consistency of the response.
            ret_code = sha204c_check_crc(rx_buffer);
            if (ret_code == SHA204_SUCCESS)
            {
                // Received valid response.
                if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN)
                    // Received non-status response. We are done.
                    return ret_code;

                // Received status response.
                status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS];

                // Translate the three possible device status error codes
                // into library return codes.
                if (status_byte == SHA204_STATUS_BYTE_PARSE)
                    return SHA204_PARSE_ERROR;
                if (status_byte == SHA204_STATUS_BYTE_EXEC)
                    return SHA204_CMD_FAIL;
                if (status_byte == SHA204_STATUS_BYTE_COMM)
                {
                    // In case of the device status byte indicating a communication
                    // error this function exits the retry loop for receiving a response
                    // and enters the overall retry loop
                    // (send command / receive response).
                    ret_code = SHA204_STATUS_CRC;
                    break;
                }

                // Received status response from CheckMAC, DeriveKey, GenDig,
                // Lock, Nonce, Pause, UpdateExtra, or Write command.
                return ret_code;
            }

            else
            {
                // Received response with incorrect CRC.
                ret_code_resync = sha204c_resync(rx_size, rx_buffer);
                if (ret_code_resync == SHA204_SUCCESS)
                    // We did not have to wake up the device. Try receiving response again.
                    continue;
                if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP)
                    // We could re-synchronize, but only after waking up the device.
                    // Re-send command.
                    break;
                else
                    // We failed to re-synchronize.
                    return ret_code;
            } // block end of check response consistency

        } // block end of receive retry loop

    } // block end of send and receive retry loop

    return ret_code;
}