Exemplo n.º 1
0
/**
 * \brief This function runs a SHA204 Wakeup / Sleep test.
 *
 * This test wakes up the device, reads its Wakeup response,
 * and sends a Sleep command. It then sends a command and
 * expects a response timeout to verify that the device has
 * gone to sleep.
 *
 * \param test current test case
 */
static void test_sha204_wakeup(const struct test_case *test)
{
	uint8_t sha204_status = SHA204_SUCCESS;

	// Catch watchdog timeout in case no Security Xplained board is connected.
	if ((reset_cause_get_causes() & CHIP_RESET_CAUSE_WDT) != CHIP_RESET_CAUSE_WDT) {
		reset_cause_clear_causes(CHIP_RESET_CAUSE_POR |
				CHIP_RESET_CAUSE_EXTRST |
				CHIP_RESET_CAUSE_BOD_CPU |
				CHIP_RESET_CAUSE_OCD |
				CHIP_RESET_CAUSE_SOFT | CHIP_RESET_CAUSE_SPIKE);
	} else {
		wdt_disable();
		reset_cause_clear_causes(CHIP_RESET_CAUSE_WDT);
		test_assert_false(test, sha204_status == SHA204_SUCCESS, "No Device.");
		return;
	}

	/* Start watchdog timer. */
	wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_250CLK); // 250 ms
	wdt_enable();
			
	uint8_t response[DEVREV_RSP_SIZE];
	
	success = false;
	
	sha204_status = sha204c_wakeup(response);
	// The TWI_M driver is not hanging. We can disable the watchdog now.
	wdt_disable();
	test_assert_true(test, sha204_status == SHA204_SUCCESS, "Sending Wakeup token failed.");
	
	sha204_status = sha204p_sleep();
	test_assert_true(test, sha204_status == SHA204_SUCCESS, "Sending Sleep command failed.");
	
	// Make sure the device is asleep. The code below works only for TWI, not for SWI,
	// because there is no acknowledging of a TWI address for SWI.
	uint8_t command[DEVREV_COUNT] = {DEVREV_COUNT, SHA204_DEVREV, 0, 0, 0, 0x03, 0x5d};
	sha204_status = sha204p_send_command(sizeof(command), command);
	test_assert_false(test, sha204_status == SHA204_SUCCESS, "Device is not asleep.");

	success = true;
}
Exemplo n.º 2
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;
}