mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #1105 from 0xc0170/dev_asynch_unit_tests
Asynch Unit tests (Serial, SPI, I2C, low power ticker)pull/1107/head
commit
b788b13841
|
|
@ -0,0 +1,201 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "TestHarness.h"
|
||||
#include "mbed.h"
|
||||
|
||||
/* EEPROM 24LC256 Test Unit, to test I2C asynchronous communication.
|
||||
*/
|
||||
|
||||
#if !DEVICE_I2C || !DEVICE_I2C_ASYNCH
|
||||
#error i2c_master_eeprom_asynch requires asynch I2C
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_K64F)
|
||||
#define TEST_SDA_PIN PTE25
|
||||
#define TEST_SCL_PIN PTE24
|
||||
#else
|
||||
#error Target not supported
|
||||
#endif
|
||||
|
||||
#define PATTERN_MASK 0x66, ~0x66, 0x00, 0xFF, 0xA5, 0x5A, 0xF0, 0x0F
|
||||
|
||||
volatile int why;
|
||||
volatile bool complete;
|
||||
void cbdone(int event) {
|
||||
complete = true;
|
||||
why = event;
|
||||
}
|
||||
|
||||
const unsigned char pattern[] = { PATTERN_MASK };
|
||||
|
||||
TEST_GROUP(I2C_Master_EEPROM_Asynchronous)
|
||||
{
|
||||
I2C *obj;
|
||||
const int eeprom_address = 0xA0;
|
||||
event_callback_t callback;
|
||||
|
||||
void setup() {
|
||||
obj = new I2C(TEST_SDA_PIN, TEST_SCL_PIN);
|
||||
obj->frequency(400000);
|
||||
complete = false;
|
||||
why = 0;
|
||||
callback.attach(cbdone);
|
||||
}
|
||||
|
||||
void teardown() {
|
||||
delete obj;
|
||||
obj = NULL;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST(I2C_Master_EEPROM_Asynchronous, tx_rx_one_byte_separate_transactions)
|
||||
{
|
||||
int rc;
|
||||
char data[] = { 0, 0, 0x66};
|
||||
|
||||
rc = obj->transfer(eeprom_address, data, sizeof(data), NULL, 0, callback, I2C_EVENT_ALL, false);
|
||||
CHECK_EQUAL(0, rc);
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
|
||||
CHECK_EQUAL(why, I2C_EVENT_TRANSFER_COMPLETE);
|
||||
|
||||
// wait until slave is ready
|
||||
do {
|
||||
complete = 0;
|
||||
why = 0;
|
||||
obj->transfer(eeprom_address, NULL, 0, NULL, 0, callback, I2C_EVENT_ALL, false);
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
} while (why != I2C_EVENT_TRANSFER_COMPLETE);
|
||||
|
||||
|
||||
// write the address for reading (0,0) then start reading data
|
||||
data[0] = 0;
|
||||
data[1] = 0;
|
||||
data[2] = 0;
|
||||
why = 0;
|
||||
complete = 0;
|
||||
obj->transfer(eeprom_address, data, 2, NULL, 0, callback, I2C_EVENT_ALL, true);
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
CHECK_EQUAL(why, I2C_EVENT_TRANSFER_COMPLETE);
|
||||
|
||||
data[0] = 0;
|
||||
data[1] = 0;
|
||||
data[2] = 0;
|
||||
why = 0;
|
||||
complete = 0;
|
||||
rc = obj->transfer(eeprom_address, NULL, 0, data, 1, callback, I2C_EVENT_ALL, false);
|
||||
CHECK_EQUAL(0, rc);
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
CHECK_EQUAL(why, I2C_EVENT_TRANSFER_COMPLETE);
|
||||
CHECK_EQUAL(data[0], 0x66);
|
||||
}
|
||||
|
||||
TEST(I2C_Master_EEPROM_Asynchronous, tx_rx_one_byte_one_transactions)
|
||||
{
|
||||
int rc;
|
||||
char send_data[] = { 0, 0, 0x66};
|
||||
rc = obj->transfer(eeprom_address, send_data, sizeof(send_data), NULL, 0, callback, I2C_EVENT_ALL, false);
|
||||
CHECK_EQUAL(0, rc)
|
||||
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
|
||||
CHECK_EQUAL(why, I2C_EVENT_TRANSFER_COMPLETE);
|
||||
|
||||
// wait until slave is ready
|
||||
do {
|
||||
complete = 0;
|
||||
why = 0;
|
||||
obj->transfer(eeprom_address, NULL, 0, NULL, 0, callback, I2C_EVENT_ALL, false);
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
} while (why != I2C_EVENT_TRANSFER_COMPLETE);
|
||||
|
||||
|
||||
send_data[0] = 0;
|
||||
send_data[1] = 0;
|
||||
send_data[2] = 0;
|
||||
char receive_data[1] = {0};
|
||||
why = 0;
|
||||
complete = 0;
|
||||
rc = obj->transfer(eeprom_address, send_data, 2, receive_data, 1, callback, I2C_EVENT_ALL, false);
|
||||
CHECK_EQUAL(0, rc);
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
|
||||
CHECK_EQUAL(why, I2C_EVENT_TRANSFER_COMPLETE);
|
||||
CHECK_EQUAL(receive_data[0], 0x66);
|
||||
}
|
||||
|
||||
TEST(I2C_Master_EEPROM_Asynchronous, tx_rx_pattern)
|
||||
{
|
||||
int rc;
|
||||
char data[] = { 0, 0, PATTERN_MASK};
|
||||
// write 8 bytes to 0x0, then read them
|
||||
rc = obj->transfer(eeprom_address, data, sizeof(data), NULL, 0, callback, I2C_EVENT_ALL, false);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
CHECK_EQUAL(why, I2C_EVENT_TRANSFER_COMPLETE);
|
||||
|
||||
// wait until slave is ready
|
||||
do {
|
||||
complete = 0;
|
||||
why = 0;
|
||||
obj->transfer(eeprom_address, NULL, 0, NULL, 0, callback, I2C_EVENT_ALL, false);
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
} while (why != I2C_EVENT_TRANSFER_COMPLETE);
|
||||
|
||||
complete = 0;
|
||||
why = 0;
|
||||
char rec_data[8] = {0};
|
||||
rc = obj->transfer(eeprom_address, rec_data, 2, NULL, 0, callback, I2C_EVENT_ALL, true);
|
||||
CHECK_EQUAL(0, rc);
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
CHECK_EQUAL(why, I2C_EVENT_TRANSFER_COMPLETE);
|
||||
|
||||
complete = 0;
|
||||
why = 0;
|
||||
rc = obj->transfer(eeprom_address, NULL, 0, rec_data, 8, callback, I2C_EVENT_ALL, false);
|
||||
CHECK_EQUAL(0, rc);
|
||||
while (!complete) {
|
||||
sleep();
|
||||
}
|
||||
CHECK_EQUAL(why, I2C_EVENT_TRANSFER_COMPLETE);
|
||||
|
||||
// received buffer match with pattern
|
||||
rc = memcmp(pattern, rec_data, sizeof(rec_data));
|
||||
CHECK_EQUAL(0, rc);
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "TestHarness.h"
|
||||
#include "mbed.h"
|
||||
#include "us_ticker_api.h"
|
||||
|
||||
/* Low power timer test.
|
||||
*/
|
||||
|
||||
#if !DEVICE_LOWPOWERTIMER
|
||||
#error This test unit requires low power to be defined for a target
|
||||
#endif
|
||||
|
||||
volatile bool complete;
|
||||
|
||||
void cbdone() {
|
||||
complete = true;
|
||||
}
|
||||
|
||||
TEST_GROUP(LowPowerTimerTest)
|
||||
{
|
||||
LowPowerTimeout *obj;
|
||||
|
||||
void setup() {
|
||||
obj = new LowPowerTimeout;
|
||||
complete = false;
|
||||
}
|
||||
|
||||
void teardown() {
|
||||
delete obj;
|
||||
obj = NULL;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// 2 second timeout using lp ticker, time is measured using us ticker
|
||||
TEST(LowPowerTimerTest, lp_ticker_callback_2sec_timeout)
|
||||
{
|
||||
timestamp_t start = us_ticker_read();
|
||||
obj->attach(&cbdone, 2.0f);
|
||||
while (!complete);
|
||||
timestamp_t end = us_ticker_read();
|
||||
|
||||
// Not accurate for longer delays, thus +/-
|
||||
if ((end - start) > 2100000) {
|
||||
printf("Error! Start: %u, end: %u. It took longer than 2.1 sec.", start, end);
|
||||
CHECK_EQUAL(0, 1);
|
||||
}
|
||||
CHECK_EQUAL(complete, 1);
|
||||
}
|
||||
|
||||
// 50 microsecond timeout
|
||||
TEST(LowPowerTimerTest, lp_ticker_callback_50us_timeout)
|
||||
{
|
||||
timestamp_t start = us_ticker_read();
|
||||
obj->attach_us(&cbdone, 50);
|
||||
while(!complete);
|
||||
timestamp_t end = us_ticker_read();
|
||||
// roughly should be around 50us +/- 500us, for example with 32kHz, it can be 32us the lowest
|
||||
CHECK_EQUAL(((end - start) > 1) && ((end - start) < 500) ,1);
|
||||
CHECK_EQUAL(complete, 1);
|
||||
}
|
||||
|
||||
// 1 milisecond timeout
|
||||
TEST(LowPowerTimerTest, lp_ticker_callback_1ms_timeout)
|
||||
{
|
||||
timestamp_t start = us_ticker_read();
|
||||
obj->attach_us(&cbdone, 1000);
|
||||
while(!complete);
|
||||
timestamp_t end = us_ticker_read();
|
||||
|
||||
CHECK_EQUAL(((end - start) > 800) && ((end - start) < 1600) ,1);
|
||||
CHECK_EQUAL(complete, 1);
|
||||
}
|
||||
|
||||
// 5 second wake up from deep sleep
|
||||
TEST(LowPowerTimerTest, lp_ticker_deepsleep_wakeup_5sec_timeout)
|
||||
{
|
||||
timestamp_t start = lp_ticker_read();
|
||||
obj->attach(&cbdone, 5.0f);
|
||||
deepsleep();
|
||||
while (!complete);
|
||||
timestamp_t end = lp_ticker_read();
|
||||
// roughly should be around 5seconds +/- 100ms
|
||||
CHECK_EQUAL(((end - start) > 4900000) && ((end - start) < 5100000) ,1);
|
||||
CHECK_EQUAL(complete, 1);
|
||||
}
|
||||
|
||||
// 1ms wake up from deep sleep
|
||||
TEST(LowPowerTimerTest, lp_ticker_deepsleep_wakeup_1ms_timeout)
|
||||
{
|
||||
timestamp_t start = lp_ticker_read();
|
||||
obj->attach(&cbdone, 0.001f);
|
||||
deepsleep();
|
||||
while (!complete);
|
||||
timestamp_t end = lp_ticker_read();
|
||||
// 1ms timeout +/- 600us
|
||||
CHECK_EQUAL(((end - start) > 400) && ((end - start) < 1600) ,1);
|
||||
CHECK_EQUAL(complete, 1);
|
||||
}
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "TestHarness.h"
|
||||
#include "mbed.h"
|
||||
|
||||
/* Serial asynch cross */
|
||||
|
||||
#if !DEVICE_SERIAL || !DEVICE_SERIAL_ASYNCH
|
||||
#error serial_asynch requires asynch Serial
|
||||
#endif
|
||||
|
||||
// Device config
|
||||
#if defined(TARGET_K64F)
|
||||
#define TEST_SERIAL_ONE_TX_PIN PTC17 // uart3
|
||||
#define TEST_SERIAL_TWO_RX_PIN PTD2 // uart2
|
||||
|
||||
#else
|
||||
|
||||
#error Target not supported
|
||||
#endif
|
||||
|
||||
// Test config
|
||||
#define SHORT_XFR 3
|
||||
#define LONG_XFR 16
|
||||
#define TEST_BYTE_TX_BASE 0x5555
|
||||
#define TEST_BYTE_RX 0x5A5A
|
||||
|
||||
volatile int tx_event_flag;
|
||||
volatile bool tx_complete;
|
||||
|
||||
volatile int rx_event_flag;
|
||||
volatile bool rx_complete;
|
||||
|
||||
void cb_tx_done(int event)
|
||||
{
|
||||
tx_complete = true;
|
||||
tx_event_flag = event;
|
||||
}
|
||||
|
||||
void cb_rx_done(int event)
|
||||
{
|
||||
rx_complete = true;
|
||||
rx_event_flag = event;
|
||||
}
|
||||
|
||||
TEST_GROUP(Serial_Asynchronous)
|
||||
{
|
||||
uint8_t tx_buf[LONG_XFR];
|
||||
uint8_t rx_buf[LONG_XFR];
|
||||
|
||||
Serial *serial_tx;
|
||||
Serial *serial_rx;
|
||||
event_callback_t tx_callback;
|
||||
event_callback_t rx_callback;
|
||||
|
||||
void setup()
|
||||
{
|
||||
serial_tx = new Serial(TEST_SERIAL_ONE_TX_PIN, NC);
|
||||
serial_rx = new Serial(NC, TEST_SERIAL_TWO_RX_PIN);
|
||||
tx_complete = false;
|
||||
tx_event_flag = 0;
|
||||
rx_complete = false;
|
||||
rx_event_flag = 0;
|
||||
tx_callback.attach(cb_tx_done);
|
||||
rx_callback.attach(cb_rx_done);
|
||||
|
||||
// Set the default value of tx_buf
|
||||
for (uint32_t i = 0; i < sizeof(tx_buf); i++) {
|
||||
tx_buf[i] = i + TEST_BYTE_TX_BASE;
|
||||
}
|
||||
memset(rx_buf, TEST_BYTE_RX, sizeof(rx_buf));
|
||||
}
|
||||
|
||||
void teardown()
|
||||
{
|
||||
delete serial_tx;
|
||||
serial_tx = NULL;
|
||||
delete serial_rx;
|
||||
serial_rx = NULL;
|
||||
|
||||
}
|
||||
|
||||
uint32_t cmpnbufc(uint8_t expect, uint8_t *actual, uint32_t offset, uint32_t end, const char *file, uint32_t line)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = offset; i < end; i++){
|
||||
if (expect != actual[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < end) {
|
||||
CHECK_EQUAL_LOCATION((int)expect, (int)actual[i], file, line);
|
||||
}
|
||||
CHECK_EQUAL_LOCATION(end, i, file, line);
|
||||
return i;
|
||||
}
|
||||
|
||||
uint32_t cmpnbuf(uint8_t *expect, uint8_t *actual, uint32_t offset, uint32_t end, const char *file, uint32_t line)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = offset; i < end; i++){
|
||||
if (expect[i] != actual[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < end) {
|
||||
CHECK_EQUAL_LOCATION((int)expect[i], (int)actual[i], file, line);
|
||||
}
|
||||
CHECK_EQUAL_LOCATION(end, i, file, line);
|
||||
return i;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST(Serial_Asynchronous, short_tx_0_rx)
|
||||
{
|
||||
int rc;
|
||||
rc = serial_tx->write(tx_buf, SHORT_XFR, tx_callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!tx_complete);
|
||||
|
||||
CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
|
||||
// rx buffer unchanged
|
||||
cmpnbufc(TEST_BYTE_RX, rx_buf, 0, sizeof(rx_buf), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
TEST(Serial_Asynchronous, short_tx_short_rx)
|
||||
{
|
||||
int rc;
|
||||
serial_rx->read(rx_buf, SHORT_XFR, rx_callback, -1);
|
||||
rc = serial_tx->write(tx_buf, SHORT_XFR, tx_callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while ((!tx_complete) || (!rx_complete));
|
||||
|
||||
CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
|
||||
CHECK_EQUAL(SERIAL_EVENT_RX_COMPLETE, rx_event_flag);
|
||||
|
||||
// Check that the receive buffer contains the fill byte.
|
||||
cmpnbuf(tx_buf, rx_buf, 0, SHORT_XFR, __FILE__, __LINE__);
|
||||
// Check that remaining portion of the receive buffer contains the rx test byte
|
||||
cmpnbufc(TEST_BYTE_RX, rx_buf, SHORT_XFR, sizeof(rx_buf), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
TEST(Serial_Asynchronous, long_tx_long_rx)
|
||||
{
|
||||
int rc;
|
||||
serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1);
|
||||
rc = serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while ((!tx_complete) || (!rx_complete));
|
||||
|
||||
CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
|
||||
CHECK_EQUAL(SERIAL_EVENT_RX_COMPLETE, rx_event_flag);
|
||||
|
||||
// Check that the receive buffer contains the fill byte.
|
||||
cmpnbuf(tx_buf, rx_buf, 0, LONG_XFR, __FILE__, __LINE__);
|
||||
// Check that remaining portion of the receive buffer contains the rx test byte
|
||||
cmpnbufc(TEST_BYTE_RX, rx_buf, LONG_XFR, sizeof(rx_buf), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
TEST(Serial_Asynchronous, rx_parity_error)
|
||||
{
|
||||
int rc;
|
||||
// Set different parity for RX and TX
|
||||
serial_rx->format(8, SerialBase::Even, 1);
|
||||
serial_tx->format(8, SerialBase::Odd, 1);
|
||||
serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1);
|
||||
rc = serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while ((!tx_complete) || (!rx_complete));
|
||||
|
||||
CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
|
||||
CHECK_EQUAL(SERIAL_EVENT_RX_PARITY_ERROR, rx_event_flag);
|
||||
}
|
||||
|
||||
TEST(Serial_Asynchronous, rx_framing_error)
|
||||
{
|
||||
int rc;
|
||||
serial_tx->baud(4800);
|
||||
serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1);
|
||||
rc = serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while ((!tx_complete) || (!rx_complete));
|
||||
|
||||
CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
|
||||
CHECK_EQUAL(SERIAL_EVENT_RX_FRAMING_ERROR, rx_event_flag);
|
||||
}
|
||||
|
||||
TEST(Serial_Asynchronous, char_matching_success)
|
||||
{
|
||||
// match found
|
||||
serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1, (uint8_t)(TEST_BYTE_TX_BASE+5));
|
||||
serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
|
||||
|
||||
while ((!tx_complete) || (!rx_complete));
|
||||
|
||||
CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
|
||||
CHECK_EQUAL(SERIAL_EVENT_RX_CHARACTER_MATCH, rx_event_flag);
|
||||
|
||||
cmpnbufc(TEST_BYTE_RX, rx_buf, 5, sizeof(rx_buf), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
TEST(Serial_Asynchronous, char_matching_failed)
|
||||
{
|
||||
// no match found (specified match char is not in tx buffer)
|
||||
serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1, (uint8_t)(TEST_BYTE_TX_BASE + sizeof(tx_buf)));
|
||||
serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
|
||||
|
||||
while ((!tx_complete) || (!rx_complete));
|
||||
|
||||
CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
|
||||
CHECK_EQUAL(SERIAL_EVENT_RX_COMPLETE, rx_event_flag);
|
||||
|
||||
cmpnbuf(tx_buf, rx_buf, 0, LONG_XFR, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
TEST(Serial_Asynchronous, char_matching_with_complete)
|
||||
{
|
||||
serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1, (uint8_t)(TEST_BYTE_TX_BASE + sizeof(tx_buf) - 1));
|
||||
serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
|
||||
|
||||
while ((!tx_complete) || (!rx_complete));
|
||||
|
||||
CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
|
||||
CHECK_EQUAL((SERIAL_EVENT_RX_COMPLETE | SERIAL_EVENT_RX_CHARACTER_MATCH), rx_event_flag);
|
||||
|
||||
cmpnbuf(tx_buf, rx_buf, 0, LONG_XFR, __FILE__, __LINE__);
|
||||
}
|
||||
|
|
@ -0,0 +1,305 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "TestHarness.h"
|
||||
#include "mbed.h"
|
||||
|
||||
#if !DEVICE_SPI || !DEVICE_SPI_ASYNCH
|
||||
#error spi_master_asynch requires asynch SPI
|
||||
#endif
|
||||
|
||||
|
||||
#define SHORT_XFR 3
|
||||
#define LONG_XFR 16
|
||||
#define TEST_BYTE0 0x00
|
||||
#define TEST_BYTE1 0x11
|
||||
#define TEST_BYTE2 0xFF
|
||||
#define TEST_BYTE3 0xAA
|
||||
#define TEST_BYTE4 0x55
|
||||
#define TEST_BYTE5 0x50
|
||||
|
||||
#define TEST_BYTE_RX TEST_BYTE3
|
||||
#define TEST_BYTE_TX_BASE TEST_BYTE5
|
||||
|
||||
#if defined(TARGET_K64F)
|
||||
#define TEST_MOSI_PIN PTD2
|
||||
#define TEST_MISO_PIN PTD3
|
||||
#define TEST_SCLK_PIN PTD1
|
||||
#define TEST_CS_PIN PTD0
|
||||
#else
|
||||
#error Target not supported
|
||||
#endif
|
||||
|
||||
volatile int why;
|
||||
volatile bool complete;
|
||||
void cbdone(int event) {
|
||||
complete = true;
|
||||
why = event;
|
||||
}
|
||||
|
||||
|
||||
TEST_GROUP(SPI_Master_Asynchronous)
|
||||
{
|
||||
uint8_t tx_buf[LONG_XFR];
|
||||
uint8_t rx_buf[LONG_XFR];
|
||||
SPI *obj;
|
||||
DigitalOut *cs;
|
||||
event_callback_t callback;
|
||||
|
||||
void setup() {
|
||||
obj = new SPI(TEST_MOSI_PIN, TEST_MISO_PIN, TEST_SCLK_PIN);
|
||||
cs = new DigitalOut(TEST_CS_PIN);
|
||||
complete = false;
|
||||
why = 0;
|
||||
callback.attach(cbdone);
|
||||
|
||||
// Set the default value of tx_buf
|
||||
for (uint32_t i = 0; i < sizeof(tx_buf); i++) {
|
||||
tx_buf[i] = i + TEST_BYTE_TX_BASE;
|
||||
}
|
||||
memset(rx_buf,TEST_BYTE_RX,sizeof(rx_buf));
|
||||
}
|
||||
void teardown() {
|
||||
delete obj;
|
||||
obj = NULL;
|
||||
delete cs;
|
||||
cs = NULL;
|
||||
}
|
||||
uint32_t cmpnbuf(uint8_t *expect, uint8_t *actual, uint32_t offset, uint32_t end, const char *file, uint32_t line)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = offset; i < end; i++){
|
||||
if (expect[i] != actual[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < end) {
|
||||
CHECK_EQUAL_LOCATION((int)expect[i], (int)actual[i], file, line);
|
||||
}
|
||||
CHECK_EQUAL_LOCATION(end, i, file, line);
|
||||
return i;
|
||||
}
|
||||
uint32_t cmpnbufc(uint8_t expect, uint8_t *actual, uint32_t offset, uint32_t end, const char *file, uint32_t line)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = offset; i < end; i++){
|
||||
if (expect != actual[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < end) {
|
||||
CHECK_EQUAL_LOCATION((int)expect, (int)actual[i], file, line);
|
||||
}
|
||||
CHECK_EQUAL_LOCATION(end, i, file, line);
|
||||
return i;
|
||||
}
|
||||
void dumpRXbuf() {
|
||||
uint32_t i;
|
||||
printf("\r\n");
|
||||
printf("RX Buffer Contents: [");
|
||||
//flushf(stdout);
|
||||
for (i = 0; i < sizeof(rx_buf); i++){
|
||||
printf("%02x",rx_buf[i]);
|
||||
if (i+1 < sizeof(rx_buf)){
|
||||
printf(",");
|
||||
}
|
||||
}
|
||||
printf("]\r\n");
|
||||
}
|
||||
};
|
||||
|
||||
// SPI write tx length: FIFO-1, read length: 0
|
||||
// Checks: Null pointer exceptions, completion event
|
||||
TEST(SPI_Master_Asynchronous, short_tx_0_rx)
|
||||
{
|
||||
int rc;
|
||||
// Write a buffer of Short Transfer length.
|
||||
rc = obj->transfer( tx_buf,SHORT_XFR,NULL,0, callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!complete);
|
||||
|
||||
// Make sure that the callback fires.
|
||||
CHECK_EQUAL(why, SPI_EVENT_COMPLETE);
|
||||
|
||||
// TODO: Check for a null pointer exception
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SPI write tx length: FIFO-1, read length: 0, non-null read pointer
|
||||
// Checks: Null pointer exceptions, completion event, canary values in read buffer
|
||||
TEST(SPI_Master_Asynchronous, short_tx_0_rx_nn)
|
||||
{
|
||||
int rc;
|
||||
// Write a buffer of Short Transfer length.
|
||||
rc = obj->transfer( tx_buf,SHORT_XFR,rx_buf,0,callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!complete);
|
||||
|
||||
// Make sure that the callback fires.
|
||||
CHECK_EQUAL(SPI_EVENT_COMPLETE, why);
|
||||
|
||||
// Check that the rx buffer is untouched
|
||||
cmpnbufc(TEST_BYTE_RX,rx_buf,0,sizeof(rx_buf),__FILE__,__LINE__);
|
||||
}
|
||||
|
||||
// SPI write tx length: 0, read length: FIFO-1
|
||||
// Checks: Receive value==fill character, completion event
|
||||
TEST(SPI_Master_Asynchronous, 0_tx_short_rx)
|
||||
{
|
||||
int rc;
|
||||
// Read a buffer of Short Transfer length.
|
||||
rc = obj->transfer( NULL,0,rx_buf,SHORT_XFR,callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!complete);
|
||||
|
||||
// Make sure that the callback fires.
|
||||
CHECK_EQUAL(SPI_EVENT_COMPLETE, why);
|
||||
|
||||
// TODO: Check for null pointer exception
|
||||
// Check that the receive buffer contains the fill byte.
|
||||
cmpnbufc(SPI_FILL_WORD,rx_buf,0,SHORT_XFR,__FILE__,__LINE__);
|
||||
// Check that remaining portion of the receive buffer contains the rx test byte
|
||||
cmpnbufc(TEST_BYTE_RX,rx_buf,SHORT_XFR,sizeof(rx_buf),__FILE__,__LINE__);
|
||||
}
|
||||
|
||||
// SPI write tx length: 0, read length: FIFO-1
|
||||
// Checks: Receive value==fill character, completion event
|
||||
TEST(SPI_Master_Asynchronous, 0_tx_nn_short_rx)
|
||||
{
|
||||
int rc;
|
||||
// Read a buffer of Short Transfer length.
|
||||
rc = obj->transfer(tx_buf,0,rx_buf,SHORT_XFR,callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!complete);
|
||||
|
||||
// Make sure that the callback fires.
|
||||
CHECK_EQUAL(SPI_EVENT_COMPLETE, why);
|
||||
|
||||
// Check that the receive buffer contains the fill byte.
|
||||
cmpnbufc(SPI_FILL_WORD,rx_buf,0,SHORT_XFR,__FILE__,__LINE__);
|
||||
// Check that remaining portion of the receive buffer contains the rx test byte
|
||||
cmpnbufc(TEST_BYTE_RX,rx_buf,SHORT_XFR,sizeof(rx_buf),__FILE__,__LINE__);
|
||||
}
|
||||
|
||||
// SPI write tx length: FIFO-1 ascending values, read length: FIFO-1
|
||||
// Checks: Receive buffer == tx buffer, completion event
|
||||
TEST(SPI_Master_Asynchronous, short_tx_short_rx)
|
||||
{
|
||||
int rc;
|
||||
// Write/Read a buffer of Long Transfer length.
|
||||
rc = obj->transfer( tx_buf,SHORT_XFR,rx_buf,SHORT_XFR,callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!complete);
|
||||
|
||||
// Make sure that the callback fires.
|
||||
CHECK_EQUAL(SPI_EVENT_COMPLETE, why);
|
||||
|
||||
// Check that the rx buffer contains the tx bytes
|
||||
cmpnbuf(tx_buf,rx_buf,0,SHORT_XFR,__FILE__,__LINE__);
|
||||
// Check that remaining portion of the receive buffer contains the rx test byte
|
||||
cmpnbufc(TEST_BYTE_RX,rx_buf,SHORT_XFR,sizeof(rx_buf),__FILE__,__LINE__);
|
||||
}
|
||||
// SPI write tx length: 2xFIFO ascending values, read length: 2xFIFO
|
||||
// Checks: Receive buffer == tx buffer, completion event
|
||||
TEST(SPI_Master_Asynchronous, long_tx_long_rx)
|
||||
{
|
||||
int rc;
|
||||
// Write/Read a buffer of Long Transfer length.
|
||||
rc = obj->transfer(tx_buf,LONG_XFR,rx_buf,LONG_XFR,callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!complete);
|
||||
|
||||
// Make sure that the callback fires.
|
||||
CHECK_EQUAL(SPI_EVENT_COMPLETE, why);
|
||||
|
||||
//dumpRXbuf();
|
||||
// Check that the rx buffer contains the tx bytes
|
||||
cmpnbuf(tx_buf,rx_buf,0,LONG_XFR,__FILE__,__LINE__);
|
||||
// Check that remaining portion of the receive buffer contains the rx test byte
|
||||
cmpnbufc(TEST_BYTE_RX,rx_buf,LONG_XFR,sizeof(rx_buf),__FILE__,__LINE__);
|
||||
}
|
||||
|
||||
// SPI write tx length: 2xFIFO, ascending, read length: FIFO-1
|
||||
// Checks: Receive buffer == tx buffer, completion event, read buffer overflow
|
||||
TEST(SPI_Master_Asynchronous, long_tx_short_rx)
|
||||
{
|
||||
int rc;
|
||||
// Write a buffer of Short Transfer length.
|
||||
rc = obj->transfer(tx_buf,LONG_XFR,rx_buf,SHORT_XFR,callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!complete);
|
||||
|
||||
// Make sure that the callback fires.
|
||||
CHECK_EQUAL(SPI_EVENT_COMPLETE, why);
|
||||
|
||||
// Check that the rx buffer contains the tx bytes
|
||||
cmpnbuf(tx_buf,rx_buf,0,SHORT_XFR,__FILE__,__LINE__);
|
||||
// Check that remaining portion of the receive buffer contains the rx test byte
|
||||
cmpnbufc(TEST_BYTE_RX,rx_buf,SHORT_XFR,sizeof(rx_buf),__FILE__,__LINE__);
|
||||
}
|
||||
|
||||
// SPI write tx length: FIFO-1, ascending, read length: 2xFIFO
|
||||
// Checks: Receive buffer == tx buffer, then fill, completion event
|
||||
TEST(SPI_Master_Asynchronous, short_tx_long_rx)
|
||||
{
|
||||
int rc;
|
||||
// Write a buffer of Short Transfer length.
|
||||
rc = obj->transfer(tx_buf,SHORT_XFR,rx_buf,LONG_XFR,callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!complete);
|
||||
|
||||
// Make sure that the callback fires.
|
||||
CHECK_EQUAL(SPI_EVENT_COMPLETE, why);
|
||||
|
||||
//dumpRXbuf();
|
||||
// Check that the rx buffer contains the tx bytes
|
||||
cmpnbuf(tx_buf,rx_buf,0,SHORT_XFR,__FILE__,__LINE__);
|
||||
// Check that the rx buffer contains the tx fill bytes
|
||||
cmpnbufc(SPI_FILL_WORD,rx_buf,SHORT_XFR,LONG_XFR,__FILE__,__LINE__);
|
||||
// Check that remaining portion of the receive buffer contains the rx test byte
|
||||
cmpnbufc(TEST_BYTE_RX,rx_buf,LONG_XFR,sizeof(rx_buf),__FILE__,__LINE__);
|
||||
}
|
||||
|
||||
TEST(SPI_Master_Asynchronous, queue_test)
|
||||
{
|
||||
int rc;
|
||||
// Write/Read a buffer of Long Transfer length.
|
||||
rc = obj->transfer( tx_buf,4,rx_buf,4,callback, 0);
|
||||
CHECK_EQUAL(0, rc);
|
||||
rc = obj->transfer( &tx_buf[4],4, &rx_buf[4],4,callback, 0);
|
||||
CHECK_EQUAL(0, rc);
|
||||
rc = obj->transfer( &tx_buf[8],4, &rx_buf[8],4,callback, -1);
|
||||
CHECK_EQUAL(0, rc);
|
||||
|
||||
while (!complete);
|
||||
|
||||
// Make sure that the callback fires.
|
||||
CHECK_EQUAL(SPI_EVENT_COMPLETE, why);
|
||||
|
||||
// Check that the rx buffer contains the tx bytes
|
||||
cmpnbuf(tx_buf,rx_buf,0,12,__FILE__,__LINE__);
|
||||
// Check that remaining portion of the receive buffer contains the rx test byte
|
||||
cmpnbufc(TEST_BYTE_RX,rx_buf,12,sizeof(rx_buf),__FILE__,__LINE__);
|
||||
}
|
||||
|
|
@ -999,6 +999,30 @@ TESTS = [
|
|||
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, CPPUTEST_LIBRARY],
|
||||
"automated": False,
|
||||
},
|
||||
{
|
||||
"id": "UT_I2C_EEPROM_ASYNCH", "description": "I2C Asynch eeprom",
|
||||
"source_dir": join(TEST_DIR, "utest", "i2c_eeprom_asynch"),
|
||||
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, CPPUTEST_LIBRARY],
|
||||
"automated": False,
|
||||
},
|
||||
{
|
||||
"id": "UT_SERIAL_ASYNCH", "description": "Asynch serial test (req 2 serial peripherals)",
|
||||
"source_dir": join(TEST_DIR, "utest", "serial_asynch"),
|
||||
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, CPPUTEST_LIBRARY],
|
||||
"automated": False,
|
||||
},
|
||||
{
|
||||
"id": "UT_SPI_ASYNCH", "description": "Asynch spi test",
|
||||
"source_dir": join(TEST_DIR, "utest", "spi_asynch"),
|
||||
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, CPPUTEST_LIBRARY],
|
||||
"automated": False,
|
||||
},
|
||||
{
|
||||
"id": "UT_LP_TICKER", "description": "Low power ticker test",
|
||||
"source_dir": join(TEST_DIR, "utest", "lp_ticker"),
|
||||
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, CPPUTEST_LIBRARY],
|
||||
"automated": False,
|
||||
},
|
||||
|
||||
# Tests used for target information purposes
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue