Linux Audio

Check our new training course

Loading...
/*
 * Copyright (c) 2017 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <ztest.h>
#include <kernel.h>
#include <cmsis_os.h>

struct sample_data {
	int		data1;
	unsigned char	data2;
	unsigned int	data3;
};

#define MAIL1_DATA1	75663
#define MAIL1_DATA2	156
#define MAIL1_DATA3	1000001

#define MAIL2_DATA1	93567
#define MAIL2_DATA2	255
#define MAIL2_DATA3	1234567

#define TIMEOUT		500
#define Q_LEN		5

osMailQDef(mail, Q_LEN, struct sample_data);
osMailQId  mail_id;

void send_thread(void const *argument)
{
	int i;
	struct sample_data *tx_ptr;
	struct sample_data zeroblock;
	osStatus status;

	/* This is used for comparison later in the function */
	memset(&zeroblock, 0, sizeof(struct sample_data));

	status = osMailPut(mail_id, NULL);
	zassert_true(status == osErrorValue,
	 "Something's wrong with osMailPut. It is passing for NULL mail!");

	/* Wait for mail_recv to complete initial checks */
	osDelay(TIMEOUT);

	/* Prepare and send 1st mail */
	tx_ptr = osMailAlloc(mail_id, osWaitForever);
	zassert_true(tx_ptr != NULL, "Mail1 alloc failed");
	tx_ptr->data1 = MAIL1_DATA1;
	tx_ptr->data2 = MAIL1_DATA2;
	tx_ptr->data3 = MAIL1_DATA3;
	status = osMailPut(mail_id, tx_ptr);
	zassert_true(status == osOK, "osMailPut failure for mail1");

	/* Fill the queue with blocks of mails */
	for (i = 0; i < Q_LEN; i++) {

		/* Alternately use osMailAlloc and osMailCAlloc to ensure
		 * both the APIs are tested.
		 */
		if (i & 1) {
			tx_ptr = osMailCAlloc(mail_id, osWaitForever);
		} else {
			tx_ptr = osMailAlloc(mail_id, osWaitForever);
		}
		zassert_true(tx_ptr != NULL, "Mail alloc failed");

		tx_ptr->data1 = i;
		tx_ptr->data2 = i+1;
		tx_ptr->data3 = i+2;

		status = osMailPut(mail_id, tx_ptr);
		zassert_true(status == osOK,
				"osMailPut failure for mail!");
	}

	/* Try allocating mail to a full queue immediately
	 * before it is emptied out and assert failure
	 */
	tx_ptr = osMailAlloc(mail_id, 0);
	zassert_true(tx_ptr == NULL, "MailAlloc passed. Something's wrong");
	tx_ptr = osMailCAlloc(mail_id, 0);
	zassert_true(tx_ptr == NULL, "MailCAlloc passed. Something's wrong");

	/* Try allocating mail to a full queue within a duration
	 * less than TIMEOUT, before the queue is emptied out
	 */
	tx_ptr = osMailAlloc(mail_id, TIMEOUT/3);
	zassert_true(tx_ptr == NULL, "MailAlloc passed. Something's wrong");
	tx_ptr = osMailCAlloc(mail_id, TIMEOUT/3);
	zassert_true(tx_ptr == NULL, "MailCAlloc passed. Something's wrong");

	/* Send another mail after the queue is emptied */
	tx_ptr = osMailCAlloc(mail_id, TIMEOUT*2);
	zassert_true(tx_ptr != NULL, "Mail alloc failed");
	zassert_equal(memcmp(tx_ptr, &zeroblock, sizeof(struct sample_data)), 0,
		"osMailCAlloc returned memory not initialized to 0");

	tx_ptr->data1 = MAIL2_DATA1;
	tx_ptr->data2 = MAIL2_DATA2;
	tx_ptr->data3 = MAIL2_DATA3;
	status = osMailPut(mail_id, tx_ptr);
	zassert_true(status == osOK, "osMailPut failure for mail");
}

void mail_recv(void)
{
	int i;
	struct sample_data  *rx_ptr;
	osEvent  evt;
	osStatus status;

	/* Try getting mail immediately before the queue is populated */
	evt = osMailGet(mail_id, 0);
	zassert_true(evt.status == osOK,
			"Something's wrong with osMailGet!");

	/* Try receiving mail within a duration of TIMEOUT */
	evt = osMailGet(mail_id, TIMEOUT);
	zassert_true(evt.status == osEventTimeout,
		"Something's wrong with osMailGet!");

	/* Receive 1st mail */
	evt = osMailGet(mail_id, osWaitForever);
	zassert_true(evt.status == osEventMail, "osMailGet failure");

	rx_ptr = evt.value.p;
	zassert_equal(rx_ptr->data1, MAIL1_DATA1, NULL);
	zassert_equal(rx_ptr->data2, MAIL1_DATA2, NULL);
	zassert_equal(rx_ptr->data3, MAIL1_DATA3, NULL);

	status = osMailFree(mail_id, rx_ptr);
	zassert_true(status == osOK, "osMailFree failure");

	/* Wait for queue to get filled */
	osDelay(TIMEOUT);

	/* Empty the queue */
	for (i = 0; i < Q_LEN; i++) {
		evt = osMailGet(mail_id, osWaitForever);
		zassert_true(evt.status == osEventMail, "osMailGet failure");

		rx_ptr = evt.value.p;
		zassert_equal(rx_ptr->data1, i, NULL);
		zassert_equal(rx_ptr->data2, i + 1, NULL);
		zassert_equal(rx_ptr->data3, i + 2, NULL);

		status = osMailFree(mail_id, rx_ptr);
		zassert_true(status == osOK, "osMailFree failure");
	}

	/* Receive the next mail */
	evt = osMailGet(mail_id, osWaitForever);
	zassert_true(evt.status == osEventMail, "osMailGet failure");

	rx_ptr = evt.value.p;
	zassert_equal(rx_ptr->data1, MAIL2_DATA1, NULL);
	zassert_equal(rx_ptr->data2, MAIL2_DATA2, NULL);
	zassert_equal(rx_ptr->data3, MAIL2_DATA3, NULL);

	status = osMailFree(mail_id, rx_ptr);
	zassert_true(status == osOK, "osMailFree failure");
}

osThreadDef(send_thread, osPriorityNormal, 1, 0);

void test_mailq(void)
{
	osThreadId tid;

	mail_id = osMailCreate(osMailQ(mail), NULL);
	zassert_true(mail_id != NULL, "Mail creation failed");

	tid = osThreadCreate(osThread(send_thread), NULL);
	zassert_true(tid != NULL, "Thread creation failed");

	mail_recv();
}