text: /*
   * FreeRTOS Kernel V10.3.0
   * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy of
   * this software and associated documentation files (the "Software"), to deal in
   * the Software without restriction, including without limitation the rights to
   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
   * the Software, and to permit persons to whom the Software is furnished to do so,
   * subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in all
   * copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
   * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
   * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   *
   * http://www.FreeRTOS.org
   * http://aws.amazon.com/freertos
   *
   * 1 tab == 4 spaces!
   */
  
  /*
  	BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER FOR UART0.
  */
  
  /* Library includes. */
  #include "uart.h"
  #include "gpio.h"
  #include "eic.h"
  
  /* Scheduler includes. */
  #include "FreeRTOS.h"
  #include "queue.h"
  
  /* Demo application includes. */
  #include "serial.h"
  
  #define UART0_Rx_Pin 					( 0x0001<< 8 )
  #define UART0_Tx_Pin 					( 0x0001<< 9 )
  
  #define serINVALID_QUEUE				( ( QueueHandle_t ) 0 )
  #define serNO_BLOCK						( ( TickType_t ) 0 )
  
  /* Macros to turn on and off the Tx empty interrupt. */
  #define serINTERRUPT_ON()				UART0->IER |= UART_TxHalfEmpty
  #define serINTERRUPT_OFF()				UART0->IER &= ~UART_TxHalfEmpty
  
  /*-----------------------------------------------------------*/
  
  /* Queues used to hold received characters, and characters waiting to be
  transmitted. */
  static QueueHandle_t xRxedChars;
  static QueueHandle_t xCharsForTx;
  
  /*-----------------------------------------------------------*/
  
  /* Interrupt entry point written in the assembler file serialISR.s79. */
  extern void vSerialISREntry( void );
  
  /* The interrupt service routine - called from the assembly entry point. */
  __arm void vSerialISR( void );
  
  /*-----------------------------------------------------------*/
  
  /*
   * See the serial2.h header file.
   */
  xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )
  {
  xComPortHandle xReturn;
  	
  	/* Create the queues used to hold Rx and Tx characters. */
  	xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
  	xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
  
  	/* If the queues were created correctly then setup the serial port
  	hardware. */
  	if( ( xRxedChars != serINVALID_QUEUE ) && ( xCharsForTx != serINVALID_QUEUE ) )
  	{
  		portENTER_CRITICAL();
  		{
  			/* Setup the UART port pins. */
  			GPIO_Config( GPIO0, UART0_Tx_Pin, GPIO_AF_PP );
  			GPIO_Config( GPIO0, UART0_Rx_Pin, GPIO_IN_TRI_CMOS );
  
  			/* Configure the UART. */
  			UART_OnOffConfig( UART0, ENABLE );
  			UART_FifoConfig( UART0, DISABLE );
  			UART_FifoReset( UART0, UART_RxFIFO );
  			UART_FifoReset( UART0, UART_TxFIFO );
  			UART_LoopBackConfig(UART0, DISABLE );
  			UART_Config( UART0, ulWantedBaud, UART_NO_PARITY, UART_1_StopBits, UARTM_8D );
  			UART_RxConfig( UART0, ENABLE );
  
  			/* Configure the IEC for the UART interrupts. */
  			EIC_IRQChannelPriorityConfig( UART0_IRQChannel, 1 );
  			EIC_IRQChannelConfig( UART0_IRQChannel, ENABLE );
  			EIC_IRQConfig( ENABLE );
  			UART_ItConfig( UART0, UART_RxBufFull, ENABLE );
  		}
  		portEXIT_CRITICAL();
  	}
  	else
  	{
  		xReturn = ( xComPortHandle ) 0;
  	}
  
  	/* This demo file only supports a single port but we have to return
  	something to comply with the standard demo header file. */
  	return xReturn;
  }
  /*-----------------------------------------------------------*/
  
  signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )
  {
  	/* The port handle is not required as this driver only supports one port. */
  	( void ) pxPort;
  
  	/* Get the next character from the buffer.  Return false if no characters
  	are available, or arrive before xBlockTime expires. */
  	if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )
  	{
  		return pdTRUE;
  	}
  	else
  	{
  		return pdFALSE;
  	}
  }
  /*-----------------------------------------------------------*/
  
  void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )
  {
  signed char *pxNext;
  
  	/* A couple of parameters that this port does not use. */
  	( void ) usStringLength;
  	( void ) pxPort;
  
  	/* NOTE: This implementation does not handle the queue being full as no
  	block time is used! */
  
  	/* The port handle is not required as this driver only supports UART0. */
  	( void ) pxPort;
  
  	/* Send each character in the string, one at a time. */
  	pxNext = ( signed char * ) pcString;
  	while( *pxNext )
  	{
  		xSerialPutChar( pxPort, *pxNext, serNO_BLOCK );
  		pxNext++;
  	}
  }
  /*-----------------------------------------------------------*/
  
  signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )
  {
  	/* Place the character in the queue of characters to be transmitted. */
  	if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )
  	{
  		return pdFAIL;
  	}
  
  	/* Turn on the Tx interrupt so the ISR will remove the character from the
  	queue and send it.   This does not need to be in a critical section as
  	if the interrupt has already removed the character the next interrupt
  	will simply turn off the Tx interrupt again. */
  	serINTERRUPT_ON();
  
  	return pdPASS;
  }
  /*-----------------------------------------------------------*/
  
  void vSerialClose( xComPortHandle xPort )
  {
  	/* Not supported as not required by the demo application. */
  }
  /*-----------------------------------------------------------*/
  
  /* Serial port ISR.  This can cause a context switch so is not defined as a
  standard ISR using the __irq keyword.  Instead a wrapper function is defined
  within serialISR.s79 which in turn calls this function.  See the port
  documentation on the FreeRTOS.org website for more information. */
  __arm void vSerialISR( void )
  {
  unsigned short usStatus;
  signed char cChar;
  portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
  
  	/* What caused the interrupt? */
  	usStatus = UART_FlagStatus( UART0 );
  
  	if( usStatus & UART_TxHalfEmpty )
  	{
  		/* The interrupt was caused by the THR becoming empty.  Are there any
  		more characters to transmit? */
  		if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
  		{
  			/* A character was retrieved from the queue so can be sent to the
  			THR now. */
  			UART0->TxBUFR = cChar;
  		}
  		else
  		{
  			/* Queue empty, nothing to send so turn off the Tx interrupt. */
  			serINTERRUPT_OFF();
  		}		
  	}
  
  	if( usStatus & 	UART_RxBufFull )
  	{
  		/* The interrupt was caused by a character being received.  Grab the
  		character from the RHR and place it in the queue of received
  		characters. */
  		cChar = UART0->RxBUFR;
  		xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
  	}
  
  	/* If a task was woken by either a character being received or a character
  	being transmitted then we may need to switch to another task. */
  	portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
  
  	/* End the interrupt in the EIC. */
  	portCLEAR_EIC();
  }
  
  
  
  
  
  	
  