This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

semaphores on TMS570 FreeRTOS.

Other Parts Discussed in Thread: HALCOGEN, TMS570LS3137

/**
* @file ht_spi.c
* @brief SPI Communication Function Source File
* @date 07.May.2014
* @author hwangroy
* @version 00.0.01
*
* (c) Hunter Technology R&D Center. 
*
* This file contains:
* - function 
* .
* SPI Comunication.
*
* Configure driver code generation:
*	@ Driver Enabable 
*	- Enable SPI1 driver
*
*	@ SPI1->SPI1 Data Formats Config
*	- Data Format0 Baudrate : 4500.000
*	- Charlen : 8
*
*	@ SPI1->SPI1 Delays Config
*	- Chip Select Active to Transmit Start : 6(100.000ms)
*	- Transmit End to Chip Select Inavtive : 1(25.000ms)
*
*	@ PINMUX->Pin Muxing
*	- MIBSPI1 Enable
*    - MIBSPI1SOMI_1, MIBSPI1SIMO_1 Diable
*    - MIBSPI1NCS_4, MIBSPI1NCS_5 Diable
*
*    @ VIM
*    - MIBSPI1 high Enable
*
*   @ Code Generate code click 
*/

#include "FreeRTOS.h"
#include "os_task.h"
#include "os_semphr.h"

#include "ht_spi.h"

typedef struct {
	xSemaphoreHandle xSema;
	portTickType timeout;
} g_spiState;

static g_spiState Spi_State[5U];
static xSemaphoreHandle xSema;

extern g_spiPacket g_spiPacket_t[5U];

extern void spiNotification(spiBASE_t *spi, uint32 flags);

/**
*	@fn sint32 HTT_InitSPI4(void)
*	@brief Initializes SPI4 Driver
*	@param[in] N/A:
*	@return N/A:
*	@remarks This function initializes at SPI Communication.
*/
sint32 HTT_InitSPI4(void) {
	sint32 init_spi4_ret = 0;
    /** @b initialize @b SPI4 */

    /** bring SPI out of reset */
    spiREG4->GCR0 = 0U;
    spiREG4->GCR0 = 1U;

    /** SPI4 master mode and clock configuration */
    spiREG4->GCR1 = (spiREG4->GCR1 & 0xFFFFFFFCU) | ((uint32)((uint32)1U << 1U)  /* CLOKMOD */
                  | 1U);  /* MASTER */

//	spiREG4->GCR1 |= (uint32)((uint32)1U << 16U);		/* Internal Loop-Back Test */

    /** SPI4 enable pin configuration */
    spiREG4->INT0 = (spiREG4->INT0 & 0xFEFFFFFFU) | (uint32)((uint32)0U << 24U);  /* ENABLE HIGHZ */

    /** - Delays */
    spiREG4->DELAY = (uint32)((uint32)8U << 24U)  /* C2TDELAY */
                   | (uint32)((uint32)3U << 16U)  /* T2CDELAY */
                   | (uint32)((uint32)0U << 8U)   /* T2EDELAY */
                   | (uint32)((uint32)0U << 0U);  /* C2EDELAY */

    /** - Data Format 0 */
    spiREG4->FMT0 = (uint32)((uint32)0U << 24U)  /* wdelay */
                  | (uint32)((uint32)0U << 23U)  /* parity Polarity */
                  | (uint32)((uint32)0U << 22U)  /* parity enable */
                  | (uint32)((uint32)0U << 21U)  /* wait on enable */
                  | (uint32)((uint32)0U << 20U)  /* shift direction */
                  | (uint32)((uint32)0U << 17U)  /* clock polarity */
                  | (uint32)((uint32)1U << 16U)  /* clock phase */
                  | (uint32)((uint32)177U << 8U) /* baudrate prescale */
                  | (uint32)((uint32)8U << 0U);  /* data word length */

    /** - Data Format 1 */
    spiREG4->FMT1 = (uint32)((uint32)0U << 24U)  /* wdelay */
                  | (uint32)((uint32)0U << 23U)  /* parity Polarity */
                  | (uint32)((uint32)0U << 22U)  /* parity enable */
                  | (uint32)((uint32)0U << 21U)  /* wait on enable */
                  | (uint32)((uint32)0U << 20U)  /* shift direction */
                  | (uint32)((uint32)0U << 17U)  /* clock polarity */
                  | (uint32)((uint32)0U << 16U)  /* clock phase */
                  | (uint32)((uint32)79U << 8U) /* baudrate prescale */
                  | (uint32)((uint32)16U << 0U);  /* data word length */

    /** - Data Format 2 */
    spiREG4->FMT2 = (uint32)((uint32)0U << 24U)  /* wdelay */
                  | (uint32)((uint32)0U << 23U)  /* parity Polarity */
                  | (uint32)((uint32)0U << 22U)  /* parity enable */
                  | (uint32)((uint32)0U << 21U)  /* wait on enable */
                  | (uint32)((uint32)0U << 20U)  /* shift direction */
                  | (uint32)((uint32)0U << 17U)  /* clock polarity */
                  | (uint32)((uint32)0U << 16U)  /* clock phase */
                  | (uint32)((uint32)79U << 8U) /* baudrate prescale */
                  | (uint32)((uint32)16U << 0U);  /* data word length */

    /** - Data Format 3 */
    spiREG4->FMT3 = (uint32)((uint32)0U << 24U)  /* wdelay */
                  | (uint32)((uint32)0U << 23U)  /* parity Polarity */
                  | (uint32)((uint32)0U << 22U)  /* parity enable */
                  | (uint32)((uint32)0U << 21U)  /* wait on enable */
                  | (uint32)((uint32)0U << 20U)  /* shift direction */
                  | (uint32)((uint32)0U << 17U)  /* clock polarity */
                  | (uint32)((uint32)0U << 16U)  /* clock phase */
                  | (uint32)((uint32)79U << 8U) /* baudrate prescale */
                  | (uint32)((uint32)16U << 0U);  /* data word length */

    /** - set interrupt levels */
    spiREG4->LVL = (uint32)((uint32)0U << 9U)  /* TXINT */
                 | (uint32)((uint32)0U << 8U)  /* RXINT */
                 | (uint32)((uint32)0U << 6U)  /* OVRNINT */
                 | (uint32)((uint32)0U << 4U)  /* BITERR */
                 | (uint32)((uint32)0U << 3U)  /* DESYNC */
                 | (uint32)((uint32)0U << 2U)  /* PARERR */
                 | (uint32)((uint32)0U << 1U) /* TIMEOUT */
                 | (uint32)((uint32)0U << 0U);  /* DLENERR */

    /** - clear any pending interrupts */
    spiREG4->FLG |= 0xFFFFU;

    /** - enable interrupts */
    spiREG4->INT0 = (spiREG4->INT0 & 0xFFFF0000U)
                  | (uint32)((uint32)0U << 9U)  /* TXINT */
                  | (uint32)((uint32)0U << 8U)  /* RXINT */
                  | (uint32)((uint32)0U << 6U)  /* OVRNINT */
                  | (uint32)((uint32)0U << 4U)  /* BITERR */
                  | (uint32)((uint32)0U << 3U)  /* DESYNC */
                  | (uint32)((uint32)0U << 2U)  /* PARERR */
                  | (uint32)((uint32)0U << 1U) /* TIMEOUT */
                  | (uint32)((uint32)0U << 0U);  /* DLENERR */

    /** @b initialize @b SPI4 @b Port */

    /** - SPI4 Port output values */
    spiREG4->PC3 =    (uint32)((uint32)1U << 0U)  /* SCS[0] */
                    | (uint32)((uint32)0U << 8U)  /* ENA */
                    | (uint32)((uint32)0U << 9U)  /* CLK */
                    | (uint32)((uint32)0U << 10U)  /* SIMO */
                    | (uint32)((uint32)0U << 11U); /* SOMI */

    /** - SPI4 Port direction */
    spiREG4->PC1  =   (uint32)((uint32)1U << 0U)  /* SCS[0] */
                    | (uint32)((uint32)0U << 8U)  /* ENA */
                    | (uint32)((uint32)1U << 9U)  /* CLK */
                    | (uint32)((uint32)1U << 10U)  /* SIMO */
                    | (uint32)((uint32)0U << 11U); /* SOMI */

    /** - SPI4 Port open drain enable */
    spiREG4->PC6  =   (uint32)((uint32)0U << 0U)  /* SCS[0] */
                    | (uint32)((uint32)0U << 8U)  /* ENA */
                    | (uint32)((uint32)0U << 9U)  /* CLK */
                    | (uint32)((uint32)0U << 10U)  /* SIMO */
                    | (uint32)((uint32)0U << 11U); /* SOMI */

    /** - SPI4 Port pullup / pulldown selection */
    spiREG4->PC8  =   (uint32)((uint32)1U << 0U)  /* SCS[0] */
                    | (uint32)((uint32)1U << 8U)  /* ENA */
                    | (uint32)((uint32)1U << 9U)  /* CLK */
                    | (uint32)((uint32)1U << 10U)  /* SIMO */
                    | (uint32)((uint32)1U << 11U); /* SOMI */

    /** - SPI4 Port pullup / pulldown enable*/
    spiREG4->PC7  =   (uint32)((uint32)0U << 0U)  /* SCS[0] */
                    | (uint32)((uint32)0U << 8U)  /* ENA */
                    | (uint32)((uint32)0U << 9U)  /* CLK */
                    | (uint32)((uint32)0U << 10U)  /* SIMO */
                    | (uint32)((uint32)0U << 11U); /* SOMI */

    /* SPI4 set all pins to functional */
    spiREG4->PC0  =   (uint32)((uint32)1U << 0U)  /* SCS[0] */
                    | (uint32)((uint32)1U << 8U)  /* ENA */
                    | (uint32)((uint32)1U << 9U)  /* CLK */
                    | (uint32)((uint32)1U << 10U)  /* SIMO */
                    | (uint32)((uint32)1U << 11U); /* SOMI */

    /** - Initialize TX and RX data buffer Status */
    g_spiPacket_t[3U].tx_data_status  = SPI_READY;
    g_spiPacket_t[3U].rx_data_status  = SPI_READY;

    /** - Finally start SPI4 */
    spiREG4->GCR1 = (spiREG4->GCR1 & 0xFEFFFFFFU) | 0x01000000U;

	vSemaphoreCreateBinary(xSema);
	Spi_State[3U].timeout = 100;
	if(xSema == NULL) {
		init_spi4_ret = -1;
	}


	return init_spi4_ret;
}

/**
*	@fn sint32 HTT_SendSPI(spiBASE_t *spi, uint8 ch, uint8 format, uint8 * srcbuff, uint32 blocksize)
*	@brief Send a SPI message
*	@param[in] spi : Node Point to SPI Node.
*	@param[in] ch : Slave Device Channel.
*	@param[in] format : Data Format Select.
*	@param[in] srcbuff : Data Pointer to SPI Send data.
*	@param[in] blocksize : Data size to SPI Send data.
*	@return The function will return:
*		- 0: The sends of the SPI driver the Send Data was successful.
*		- -1: The sends of the SPI driver the Send Data wasn't successful.
*   @remarks This function send to the slave device using SPI Communication.
*/
sint32 HTT_SendSPI(spiBASE_t *spi, uint8 ch, uint8 format, uint8 * srcbuff, uint32 blocksize) {
	sint32 send_spi_ret = 0;
	uint32 index = (spi == spiREG1) ? 0U :((spi==spiREG2) ? 1U : ((spi==spiREG3) ? 2U:((spi==spiREG4) ? 3U:4U)));
	uint8 sendch = (ch == 0U) ? (uint8)SPI_CS_0 :((ch == 1U) ? (uint8)SPI_CS_1 :((ch == 2U) ? (uint8)SPI_CS_2 :((ch == 3U) ? (uint8)SPI_CS_3: (uint8)0xFFU)));
	SPIDATAFMT_t sendformat = (format == 0U) ? (uint8)SPI_FMT_0 :((format == 1U) ? (uint8)SPI_FMT_1 :((format == 2U) ? (uint8)SPI_FMT_2 :((format == 3U) ? (uint8)SPI_FMT_3: (uint8)0xFFU)));
	spiDAT1_t dataconfig1_t;

	/* MibSpi Test Source */
	dataconfig1_t.CS_HOLD = TRUE;
	dataconfig1_t.WDEL = TRUE;
	dataconfig1_t.DFSEL = sendformat;
	dataconfig1_t.CSNR = sendch;

    g_spiPacket_t[index].tx_length = blocksize;
    g_spiPacket_t[index].txdata_ptr   = srcbuff;
    g_spiPacket_t[index].g_spiDataFormat = dataconfig1_t;
    g_spiPacket_t[index].tx_data_status = SPI_PENDING;

	spi->INT0 |= 0x0200U;

	while(g_spiPacket_t[index].tx_data_status == SPI_PENDING) {
		;
	}
	return send_spi_ret;
}

/**
*	@fn sint32 HTT_ReceiveSPI(spiBASE_t *spi, uint8 ch, uint8 format, uint8 * destbuff, uint32 blocksize)
*	@brief Received a SPI message
*	@param[in] spi : Node Point to SPI Node.
*	@param[in] ch : Slave Device Channel.
*	@param[in] format : Data Format Select.
*	@param[in] srcbuff : Data Pointer to SPI Received data.
*	@param[in] blocksize : Data size to SPI Received data.
*	@return N/A:
*   @remarks This function receive from the slave device using SPI Communication.
*/
sint32 HTT_ReceiveSPI(spiBASE_t *spi, uint8 ch, uint8 format, uint8 * destbuff, uint32 blocksize) {
	sint32 receive_spi_ret = 0;
	uint32 index = (spi == spiREG1) ? 0U :((spi==spiREG2) ? 1U : ((spi==spiREG3) ? 2U:((spi==spiREG4) ? 3U:4U)));
	uint8 recech = (ch == 0U) ? (uint8)SPI_CS_0 :((ch == 1U) ? (uint8)SPI_CS_1 :((ch == 2U) ? (uint8)SPI_CS_2 :((ch == 3U) ? (uint8)SPI_CS_3: (uint8)0xFFU)));
	SPIDATAFMT_t receformat = (format == 0U) ? (uint8)SPI_FMT_0 :((format == 1U) ? (uint8)SPI_FMT_1 :((format == 2U) ? (uint8)SPI_FMT_2 :((format == 3U) ? (uint8)SPI_FMT_3: (uint8)0xFFU)));
	spiDAT1_t dataconfig1_t;
	
	/* MibSpi Test Source */
	dataconfig1_t.CS_HOLD = TRUE;
	dataconfig1_t.WDEL = TRUE;
	dataconfig1_t.DFSEL = receformat;
	dataconfig1_t.CSNR = recech;

    g_spiPacket_t[index].rx_length = blocksize;
    g_spiPacket_t[index].rxdata_ptr   = destbuff;
    g_spiPacket_t[index].g_spiDataFormat = dataconfig1_t;
    g_spiPacket_t[index].rx_data_status = SPI_PENDING;

	spi->INT0 |= 0x0100U;

	while(g_spiPacket_t[index].rx_data_status == SPI_PENDING) {
		;
	}

	return receive_spi_ret;
}

/**
*	@fn sint32 HTT_SendAndReceiveSPI(spiBASE_t *spi, uint8 ch, uint8 format, uint8 * srcbuff, uint32 src_size, uint8 * destbuff, uint32 des_size)
*	@brief Send a Receive SPI message
*	@param[in] spi : Node Point to SPI Node.
*	@param[in] ch : Slave Device Channel.
*	@param[in] format : Data Format Select.
*	@param[in] srcbuff : Data Pointer to SPI Send data.
*	@param[in] src_size : Data size to SPI Send data.
*	@param[in] destbuff : Data Pointer to SPI Received data.
*	@param[in] des_size : Data size to SPI Received data.
*	@return N/A:
*   @remarks This function send and receive to the slave device using SPI Communication.
*/
sint32 HTT_SendAndReceiveSPI(spiBASE_t *spi, uint8 ch, uint8 format, uint8 * srcbuff, uint32 src_size, uint8 * destbuff, uint32 des_size) {
	sint32 sendandrec_spi_ret = 0;
	uint32 index = (spi == spiREG1) ? 0U :((spi==spiREG2) ? 1U : ((spi==spiREG3) ? 2U:((spi==spiREG4) ? 3U:4U)));
	uint8 sendandrecech = (ch == 0U) ? (uint8)SPI_CS_0 :((ch == 1U) ? (uint8)SPI_CS_1 :((ch == 2U) ? (uint8)SPI_CS_2 :((ch == 3U) ? (uint8)SPI_CS_3: (uint8)0xFFU)));
	SPIDATAFMT_t sendandrecefrormat = (format == 0U) ? (uint8)SPI_FMT_0 :((format == 1U) ? (uint8)SPI_FMT_1 :((format == 2U) ? (uint8)SPI_FMT_2 :((format == 3U) ? (uint8)SPI_FMT_3: (uint8)0xFFU)));
	spiDAT1_t dataconfig1_t;
	
	/* MibSpi Test Source */
	dataconfig1_t.CS_HOLD = TRUE;
	dataconfig1_t.WDEL = TRUE;
	dataconfig1_t.DFSEL = sendandrecefrormat;
	dataconfig1_t.CSNR = sendandrecech;

    g_spiPacket_t[index].tx_length       = src_size;
    g_spiPacket_t[index].rx_length       = des_size;
    g_spiPacket_t[index].txdata_ptr      = srcbuff;
    g_spiPacket_t[index].rxdata_ptr      = destbuff;
    g_spiPacket_t[index].g_spiDataFormat = dataconfig1_t;
    g_spiPacket_t[index].tx_data_status  = SPI_PENDING;
    g_spiPacket_t[index].rx_data_status  = SPI_PENDING;

	spi->FLG = 0x00000000;
	spi->INT0 |= 0x0200U;
	while(g_spiPacket_t[index].tx_data_status == SPI_PENDING) {
		;
	}

	spi->FLG = 0x00000000;
	spi->INT0 |= 0x0100U;

	if(xSemaphoreTake(xSema, (portTickType)100) == pdTRUE )
    {
		while(g_spiPacket_t[index].rx_data_status == SPI_PENDING) {
			;
		}
	}
	else {
		sendandrec_spi_ret = -1;
	}
	return sendandrec_spi_ret;
}

/**
*	@fn void spiNotification(spiBASE_t *spi, uint32 flags)
*   @brief Message notification
*   @param[in] spi : Node Pointer to spi node:
*		- spiREG1: SCI1 node pointer
*		- spiREG2: SCI2 node pointer
*		- spiREG3: SCI3 node pointer
*		- spiREG4: SCI4 node pointer
*   @param[in] flags : Interrupt number of SPI:
*   @return N/A:
*   @remarks This function is called when interrupt occurs.
*/
void spiNotification(spiBASE_t *spi, uint32 flags) {
	static signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
	uint32 index = (spi == spiREG1) ? 0U :((spi==spiREG2) ? 1U : ((spi==spiREG3) ? 2U:((spi==spiREG4) ? 3U:4U)));
    uint32 vec = spi->INTVECT0;

	switch(vec)
	{

		case 0x24U: /* Receive Buffer Full Interrupt */
		{
			uint8 *destbuff;
			destbuff = g_spiPacket_t[index].rxdata_ptr;

			*destbuff = (uint16)spi->BUF;
			spi->FLG = (spi->FLG & 0x0000FFFFU) & (~(uint32)0x0100U); /* Flag Clear */ 

			/*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
			g_spiPacket_t[index].rxdata_ptr++;
			g_spiPacket_t[index].rx_length--;

			if(g_spiPacket_t[index].rx_length == 0U)
			{
				spi->INT0 = (spi->INT0 & 0x0000FFFFU) & (~(uint32)0x0100U);
				g_spiPacket_t[index].rx_data_status = SPI_COMPLETED;

				xSemaphoreGiveFromISR(xSema, &xHigherPriorityTaskWoken);
	//			xSemaphoreGive(xSema);
				
				spiEndNotification(spi);
			}
			break;
		}

		case 0x28U: /* Transmit Buffer Empty Interrupt */
		{
			volatile uint32 SpiBuf;
			uint32 Chip_Select_Hold = 0U;
			uint32 WDelay = (g_spiPacket_t[index].g_spiDataFormat.WDEL) ? 0x04000000U: 0U;
			SPIDATAFMT_t DataFormat = g_spiPacket_t[index].g_spiDataFormat.DFSEL;
			uint8 ChipSelect = g_spiPacket_t[index].g_spiDataFormat.CSNR;
			uint8 Tx_Data = *g_spiPacket_t[index].txdata_ptr;

			g_spiPacket_t[index].tx_length--;

			if((g_spiPacket_t[index].tx_length == 0U) && (g_spiPacket_t[index].rx_length == 0U))
			{
				Chip_Select_Hold = 0U;
			}
			else
			{
				Chip_Select_Hold = (g_spiPacket_t[index].g_spiDataFormat.CS_HOLD) ? 0x10000000U : 0U;
			}

			spi->DAT1 = ((uint32)DataFormat << 24U) |
						((uint32)ChipSelect << 16U) |
						(WDelay)			|
						(Chip_Select_Hold) |
						(uint32)Tx_Data;

			/*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
			g_spiPacket_t[index].txdata_ptr++;
			/* Dummy Receive read if no RX Interrupt enabled */
			if(((spi->INT0 & 0x0000FFFFU)& 0x0100U) == 0U)
			{
				while((spi->FLG & 0x00000100U) == 0x00000100U)
				{
					SpiBuf = spi->BUF;
				}
			}

			if(g_spiPacket_t[index].rx_length != 0U) {
				while((spi->FLG & 0x00000100U) == 0x00000100U) {
					SpiBuf = spi->BUF;
				}
				spi->FLG = (spi->FLG & 0x0000FFFFU) & (~(uint32)0x0100U); /* Flag Clear */ 

				if(g_spiPacket_t[index].rx_length == 1U)
				{
					Chip_Select_Hold = 0U;
				}
				else
				{
					Chip_Select_Hold = (g_spiPacket_t[index].g_spiDataFormat.CS_HOLD) ? 0x10000000U : 0U;
				}

				spi->DAT1 = ((uint32)DataFormat << 24U) |
								((uint32)ChipSelect << 16U) |
								(WDelay)		   |
								(Chip_Select_Hold) |
								(uint32)0xFF;
			}

			if(g_spiPacket_t[index].tx_length == 0U)
			{
				spi->INT0 = (spi->INT0 & 0x0000FFFFU) & (~(uint32)0x0200U); /* Disable Interrupt */
				g_spiPacket_t[index].tx_data_status = SPI_COMPLETED;
				spiEndNotification(spi);
			}
			break;
		}

		default: /* Clear Flags and return	*/
				spi->FLG = flags;
				spiNotification(spi, flags & 0xFFU);
				break;
	}
}

4188.ht_spi.h

 

I trying the FreeRTOS on TMS570LS3137. Create a project using the TMS570LS317ZWT_FREERTOS template in the HalCoGen(3.9.0).

 

I add the timeout of receive function at SPI Driver,

a. wait 100ms timeout using xSemaphoreTake() into HTT_ReceiveSPI().

b. use xSemaphoreGiveFromISR() into rx interruppt of  spiNotification().

 

If normal, The vSemaphoreTask() is obtain semaphore through xSemaphoreGiveFromISR() at SPINotification(). so, it is not problem of operate.

 

If doesn't received the data, doesn't occur the interrupt. so, The vSemaphoreTask() isn't obtain semaphore through xSemaphoreGiveFromISR() at SPINotification . vSemaphoreTask() have to return the pdFALSE, after 100ms. but, continuously wait at vSemaphoreTask().

sint32 HTT_SendAndReceiveSPI() {      

           .....

         if(xSemaphoreTake(xSema, (portTickType)100) == pdTRUE )    {

               while(g_spiPacket_t[index].rx_data_status == SPI_PENDING) {

                        ;       

                }   

                else {  

                        sendandrec_spi_ret = -1;   

                }

}

void spiNotification() {

  switch(vec)       case 0x24U:

           ...

           if(g_spiPacket_t[index].rx_length == 0U)  {

                spi->INT0 = (spi->INT0 & 0x0000FFFFU) & (~(uint32)0x0100U);

                g_spiPacket_t[index].rx_data_status = SPI_COMPLETED;

               xSemaphoreGiveFromISR(xSema, &xHigherPriorityTaskWoken);

               spiEndNotification(spi);

            }

         break;

}

  • Hello,

    I have forwarded your question to one of our Free RTOS experts. They should respond to you shortly.
  • I had define to 1 the configGENERATE_RUN_TIME_STATS in the FreeRTOSConfig.h. but,

    Occured the Error at FreeRTOS.h.

    #if ( configGENERATE_RUN_TIME_STATS == 1 )

          #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS   #error If configGENERATE_RUN_TIME_STATS is defined then          portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined.  portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base.  #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */

        #ifndef portGET_RUN_TIME_COUNTER_VALUE   #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE    #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined.  See the examples provided and the FreeRTOS web site for more information.   #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */  #endif /* portGET_RUN_TIME_COUNTER_VALUE */

    #endif /* configGENERATE_RUN_TIME_STATS */

    it does undefined of portCONFIGURE_TIMER_FOR_RUN_TIME_STATS and portGET_RUN_TIME_COUNTER_VALUE, so it occur the error.

    My thinking is seemed necessary the additional setup and set the configGENERATE_RUN_TIME_STATS.