MCUXpresso_MIMXRT1021xxxxx/boards/evkmimxrt1020/rtos_examples/freertos_lpi2c/freertos_lpi2c.c
2022-08-23 23:00:33 +08:00

344 lines
10 KiB
C

/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* Standard C Included Files */
#include <stdio.h>
#include <string.h>
/* FreeRTOS kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
/* Freescale includes. */
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_debug_console.h"
#include "fsl_lpi2c.h"
#include "fsl_lpi2c_freertos.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define EXAMPLE_I2C_MASTER_BASE (LPI2C1_BASE)
#define EXAMPLE_I2C_MASTER_IRQN (LPI2C1_IRQn)
#define EXAMPLE_I2C_SLAVE_BASE (LPI2C2_BASE)
#define EXAMPLE_I2C_SLAVE_IRQN (LPI2C2_IRQn)
/* Select USB1 PLL (480 MHz) as master lpi2c clock source */
#define LPI2C_CLOCK_SOURCE_SELECT (0U)
/* Clock divider for master lpi2c clock source */
#define LPI2C_CLOCK_SOURCE_DIVIDER (5U)
/* Get frequency of lpi2c clock */
#define LPI2C_CLOCK_FREQUENCY ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER + 1U))
/* clang-format off */
/*
The example support single board communication(one instance works as master, another
instance works as slave) or board to board communication. Defult is single board mode.
*/
#define SINGLE_BOARD 0
#define BOARD_TO_BOARD 1
#ifndef EXAMPLE_CONNECT_I2C
#define EXAMPLE_CONNECT_I2C SINGLE_BOARD
#endif /* EXAMPLE_CONNECT_I2C */
#if (EXAMPLE_CONNECT_I2C == BOARD_TO_BOARD)
#define isMASTER 0
#define isSLAVE 1
#ifndef I2C_MASTER_SLAVE
#define I2C_MASTER_SLAVE isMASTER
#endif /* I2C_MASTER_SLAVE */
#endif /* EXAMPLE_CONNECT_I2C */
#define EXAMPLE_I2C_MASTER ((LPI2C_Type *)EXAMPLE_I2C_MASTER_BASE)
#define EXAMPLE_I2C_SLAVE ((LPI2C_Type *)EXAMPLE_I2C_SLAVE_BASE)
#define I2C_MASTER_SLAVE_ADDR_7BIT (0x7EU)
#define I2C_BAUDRATE (100000) /* 100K */
#define I2C_DATA_LENGTH (32) /* MAX is 256 */
/* Task priorities. */
#define lpi2c_task_PRIORITY (configMAX_PRIORITIES - 1)
/* clang-format on */
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
uint8_t g_slave_buff[I2C_DATA_LENGTH];
uint8_t g_master_buff[I2C_DATA_LENGTH];
#if ((I2C_MASTER_SLAVE == isSLAVE) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
lpi2c_slave_handle_t g_s_handle;
#endif
volatile uint32_t timeout = 100000;
SemaphoreHandle_t lpi2c_sem;
/*******************************************************************************
* Definitions
******************************************************************************/
/* Task priorities. */
#define slave_task_PRIORITY (configMAX_PRIORITIES - 2)
#define master_task_PRIORITY (configMAX_PRIORITIES - 1)
/*******************************************************************************
* Prototypes
******************************************************************************/
static void slave_task(void *pvParameters);
#if ((I2C_MASTER_SLAVE == isMaster) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
static void master_task(void *pvParameters);
#endif
/*******************************************************************************
* Code
******************************************************************************/
int main(void)
{
uint32_t i = 0;
/* Init board hardware. */
BOARD_ConfigMPU();
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
/*Clock setting for LPI2C*/
CLOCK_SetMux(kCLOCK_Lpi2cMux, LPI2C_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_Lpi2cDiv, LPI2C_CLOCK_SOURCE_DIVIDER);
/* Set IRQ priority for freertos_lpi2c */
NVIC_SetPriority(EXAMPLE_I2C_MASTER_IRQN, 3);
NVIC_SetPriority(EXAMPLE_I2C_SLAVE_IRQN, 2);
PRINTF("\r\nLPI2C example -- MasterInterrupt_SlaveInterrupt.\r\n");
/* Set up i2c master to send data to slave */
for (i = 0; i < I2C_DATA_LENGTH; i++)
{
g_master_buff[i] = i;
}
if (xTaskCreate(slave_task, "Slave_task", configMINIMAL_STACK_SIZE + 100, NULL, slave_task_PRIORITY, NULL) !=
pdPASS)
{
PRINTF("Failed to create slave task");
while (1)
;
}
vTaskStartScheduler();
while (1)
{
}
}
/*!
* @brief Data structure and callback function for slave I2C communication.
*/
typedef struct _callback_message_t
{
status_t async_status;
SemaphoreHandle_t sem;
} callback_message_t;
#if ((I2C_MASTER_SLAVE == isSLAVE) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
static void lpi2c_slave_callback(LPI2C_Type *base, lpi2c_slave_transfer_t *xfer, void *userData)
{
callback_message_t *cb_msg = (callback_message_t *)userData;
BaseType_t reschedule = 0;
switch (xfer->event)
{
case kLPI2C_SlaveReceiveEvent:
xfer->data = g_slave_buff;
xfer->dataSize = I2C_DATA_LENGTH;
break;
case kLPI2C_SlaveCompletionEvent:
cb_msg->async_status = xfer->completionStatus;
xSemaphoreGiveFromISR(cb_msg->sem, &reschedule);
portYIELD_FROM_ISR(reschedule);
break;
default:
break;
}
}
#endif
/*!
* @brief Task responsible for slave I2C communication.
*/
static void slave_task(void *pvParameters)
{
callback_message_t cb_msg;
cb_msg.sem = xSemaphoreCreateBinary();
lpi2c_sem = cb_msg.sem;
if (cb_msg.sem == NULL)
{
PRINTF("I2C slave: Error creating semaphore\r\n");
vTaskSuspend(NULL);
}
#if ((I2C_MASTER_SLAVE == isSLAVE) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
/* Set up i2c slave first */
/*
* slaveConfig.address0 = 0U;
* slaveConfig.address1 = 0U;
* slaveConfig.addressMatchMode = kLPI2C_MatchAddress0;
* slaveConfig.filterDozeEnable = true;
* slaveConfig.filterEnable = true;
* slaveConfig.enableGeneralCall = false;
* slaveConfig.ignoreAck = false;
* slaveConfig.enableReceivedAddressRead = false;
* slaveConfig.sdaGlitchFilterWidth_ns = 0;
* slaveConfig.sclGlitchFilterWidth_ns = 0;
* slaveConfig.dataValidDelay_ns = 0;
* slaveConfig.clockHoldTime_ns = 0;
*/
lpi2c_slave_config_t slaveConfig;
LPI2C_SlaveGetDefaultConfig(&slaveConfig);
slaveConfig.address0 = I2C_MASTER_SLAVE_ADDR_7BIT;
slaveConfig.address1 = 0;
LPI2C_SlaveInit(EXAMPLE_I2C_SLAVE, &slaveConfig, LPI2C_CLOCK_FREQUENCY);
memset(&g_s_handle, 0, sizeof(g_s_handle));
memset(&g_slave_buff, 0, sizeof(g_slave_buff));
LPI2C_SlaveTransferCreateHandle(EXAMPLE_I2C_SLAVE, &g_s_handle, lpi2c_slave_callback, &cb_msg);
LPI2C_SlaveTransferNonBlocking(EXAMPLE_I2C_SLAVE, &g_s_handle,
kLPI2C_SlaveReceiveEvent | kLPI2C_SlaveCompletionEvent);
#endif
#if ((I2C_MASTER_SLAVE == isMASTER) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
if (xTaskCreate(master_task, "Master_task", configMINIMAL_STACK_SIZE + 100, NULL, master_task_PRIORITY, NULL) !=
pdPASS)
{
vTaskSuspend(NULL);
PRINTF("Failed to create master task");
}
#endif
/* Wait for transfer to finish */
if (xSemaphoreTake(cb_msg.sem, portMAX_DELAY) != pdTRUE)
{
PRINTF("Failed to take semaphore.\r\n");
}
#if ((I2C_MASTER_SLAVE == isSLAVE) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
if (cb_msg.async_status == kStatus_Success)
{
PRINTF("I2C slave transfer completed successfully. \r\n\r\n");
}
else
{
PRINTF("I2C slave transfer completed with error. \r\n\r\n");
}
int i;
/* Transfer completed. Check the data. */
for (i = 0; i < I2C_DATA_LENGTH; i++)
{
if (g_slave_buff[i] != g_master_buff[i])
{
PRINTF("\r\nError occurred in this transfer ! \r\n");
break;
}
}
if (i == 32)
{
PRINTF("\r\n Transfer successfully!\r\n ");
}
PRINTF("\r\nSlave received data :");
for (i = 0; i < I2C_DATA_LENGTH; i++)
{
if (i % 8 == 0)
{
PRINTF("\r\n");
}
PRINTF("0x%2x ", g_slave_buff[i]);
}
PRINTF("\r\n\r\n");
#endif
vTaskSuspend(NULL);
}
#if ((I2C_MASTER_SLAVE == isMaster) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
static void master_task(void *pvParameters)
{
lpi2c_master_config_t masterConfig;
lpi2c_rtos_handle_t master_rtos_handle;
lpi2c_master_transfer_t masterXfer;
status_t status;
uint32_t i = 0;
PRINTF("Master will send data :");
for (i = 0; i < I2C_DATA_LENGTH; i++)
{
if (i % 8 == 0)
{
PRINTF("\r\n");
}
PRINTF("0x%2x ", g_master_buff[i]);
}
PRINTF("\r\n\r\n");
/*
* masterConfig.debugEnable = false;
* masterConfig.ignoreAck = false;
* masterConfig.pinConfig = kLPI2C_2PinOpenDrain;
* masterConfig.baudRate_Hz = 100000U;
* masterConfig.busIdleTimeout_ns = 0;
* masterConfig.pinLowTimeout_ns = 0;
* masterConfig.sdaGlitchFilterWidth_ns = 0;
* masterConfig.sclGlitchFilterWidth_ns = 0;
*/
LPI2C_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate_Hz = I2C_BAUDRATE;
status = LPI2C_RTOS_Init(&master_rtos_handle, EXAMPLE_I2C_MASTER, &masterConfig, LPI2C_CLOCK_FREQUENCY);
if (status != kStatus_Success)
{
PRINTF("LPI2C master: Error initializing LPI2C!\r\n");
vTaskSuspend(NULL);
}
memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = I2C_MASTER_SLAVE_ADDR_7BIT;
masterXfer.direction = kLPI2C_Write;
masterXfer.subaddress = 0;
masterXfer.subaddressSize = 0;
masterXfer.data = g_master_buff;
masterXfer.dataSize = I2C_DATA_LENGTH;
masterXfer.flags = kLPI2C_TransferDefaultFlag;
status = LPI2C_RTOS_Transfer(&master_rtos_handle, &masterXfer);
if (status == kStatus_Success)
{
#if (EXAMPLE_CONNECT_I2C == BOARD_TO_BOARD)
xSemaphoreGive(lpi2c_sem);
#endif
PRINTF("I2C master transfer completed successfully.\r\n");
}
else
{
PRINTF("I2C master transfer completed with error!\r\n");
}
vTaskSuspend(NULL);
}
#endif