From 2ad87ee69c33f93deb529f82fec4d8ebde5e0fba Mon Sep 17 00:00:00 2001 From: richardbarry Date: Tue, 6 Jul 2010 21:12:01 +0000 Subject: [PATCH] Add in a basic USART driver and echo test task. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1035 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../Drivers/CircularBuffer.c | 214 ------------------ .../Drivers/CircularBuffer.h | 115 ---------- .../Drivers/SPI_Flash_ST_Eval.c | 2 +- .../Drivers/SPI_Flash_ST_Eval.h | 75 ++++++ .../Drivers/STM32_USART.c | 185 +++++++++------ .../Drivers/STM32_USART.h | 3 + Demo/CORTEX_STM32F103_GCC_Rowley/RTOSDemo.hzp | 8 +- Demo/CORTEX_STM32F103_GCC_Rowley/RTOSDemo.hzs | 19 +- Demo/CORTEX_STM32F103_GCC_Rowley/main.c | 75 +++++- .../stm32f10x_conf.h | 2 +- 10 files changed, 271 insertions(+), 427 deletions(-) delete mode 100644 Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/CircularBuffer.c delete mode 100644 Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/CircularBuffer.h create mode 100644 Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/SPI_Flash_ST_Eval.h diff --git a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/CircularBuffer.c b/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/CircularBuffer.c deleted file mode 100644 index 7f5d8f7e0..000000000 --- a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/CircularBuffer.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd. - - *************************************************************************** - * * - * If you are: * - * * - * + New to FreeRTOS, * - * + Wanting to learn FreeRTOS or multitasking in general quickly * - * + Looking for basic training, * - * + Wanting to improve your FreeRTOS skills and productivity * - * * - * then take a look at the FreeRTOS eBook * - * * - * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * - * http://www.FreeRTOS.org/Documentation * - * * - * A pdf reference manual is also available. Both are usually delivered * - * to your inbox within 20 minutes to two hours when purchased between 8am * - * and 8pm GMT (although please allow up to 24 hours in case of * - * exceptional circumstances). Thank you for your support! * - * * - *************************************************************************** - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - ***NOTE*** The exception to the GPL is included to allow you to distribute - a combined work that includes FreeRTOS without being obliged to provide the - source code for proprietary components outside of the FreeRTOS kernel. - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#include - -#include "FreeRTOS.h" -#include "CircularBuffer.h" - -/*-----------------------------------------------------------*/ - -/* See the header file for function information. */ -void vInitialiseCircularBuffer( xCircularBuffer *pxBuffer, - unsigned char *pucDataBuffer, - unsigned long ulBufferSizeInBytes, - unsigned long ulDataSizeInBytes, - void *pvTag - ) -{ - pxBuffer->pucDataBuffer = pucDataBuffer; - pxBuffer->ulBufferSizeInBytes = ulBufferSizeInBytes; - pxBuffer->pucNextByteToRead = pucDataBuffer; - pxBuffer->pucNextByteToWrite = pucDataBuffer; - pxBuffer->ulDataSizeInBytes = ulDataSizeInBytes; - pxBuffer->pvTag = pvTag; -} -/*-----------------------------------------------------------*/ - -/* See the header file for function information. */ -unsigned long ulBytesInCircularBuffer( const xCircularBuffer * const pxBuffer ) -{ -unsigned char *pucNextByteToWrite; -unsigned long ulReturn; - - if( pxBuffer->pvTag != NULL ) - { - /* Locate the position that the DMA will next write to. */ - pucNextByteToWrite = ( unsigned char * ) *( ( unsigned long * ) pxBuffer->pvTag ); - } - else - { - /* Locate the position the application will next write to. */ - pucNextByteToWrite = pxBuffer->pucNextByteToWrite; - } - - /* Has the write pointer wrapped back to the start of the buffer - compared to our read pointer? */ - if( ( unsigned long ) pucNextByteToWrite >= ( unsigned long ) pxBuffer->pucNextByteToRead ) - { - /* The write pointer is still ahead of us in the buffer. The amount of - data available is simple the gap between the two pointers. */ - ulReturn = ( unsigned long ) pucNextByteToWrite - ( unsigned long ) pxBuffer->pucNextByteToRead; - } - else - { - /* The write pointer has wrapped back to the start. The amount of data - available is equal to the data between the read pointer and the end of - the buffer...*/ - ulReturn = ( unsigned long ) &( pxBuffer->pucDataBuffer[ pxBuffer->ulBufferSizeInBytes ] ) - ( unsigned long ) pxBuffer->pucNextByteToRead; - - /*... plus the data between the start of the buffer and the write - pointer. */ - ulReturn += ( unsigned long ) pucNextByteToWrite - ( unsigned long ) pxBuffer->pucDataBuffer; - } - - return ulReturn; -} -/*-----------------------------------------------------------*/ - -unsigned long ulCopyReceivedBytes( xCircularBuffer *pxBuffer, unsigned char * pucBuffer, unsigned long ulWantedBytes ) -{ -unsigned char *pucNextByteToWrite; -unsigned long ulNumberOfBytesRead = 0, ulNumberOfBytesAvailable; - - if( pxBuffer->pvTag != NULL ) - { - /* Locate the position that the DMA will next write to. */ - pucNextByteToWrite = ( unsigned char * ) *( ( unsigned long * ) pxBuffer->pvTag ); - } - else - { - /* Locate the position that the application will next write to. */ - pucNextByteToWrite = pxBuffer->pucNextByteToWrite; - } - - if( ( unsigned long ) pucNextByteToWrite >= ( unsigned long ) pxBuffer->pucNextByteToRead ) - { - /* The write pointer has not wrapped around from our read pointer. - - Clip the number of bytes to read to the number available if the number - available is less than that wanted. */ - ulNumberOfBytesAvailable = ( unsigned long ) pucNextByteToWrite - ( unsigned long ) ( pxBuffer->pucNextByteToRead ); - - if( ulNumberOfBytesAvailable < ulWantedBytes ) - { - ulWantedBytes = ulNumberOfBytesAvailable; - } - - /* Copy the data from ulRxBuffer into the application buffer. */ - memcpy( pucBuffer, pxBuffer->pucNextByteToRead, ulWantedBytes ); - - /* Move up our read buffer. */ - pxBuffer->pucNextByteToRead += ulWantedBytes; - ulNumberOfBytesRead = ulWantedBytes; - } - else - { - /* The write pointer has wrapped around from our read pointer. Is there - enough space from our read pointer to the end of the buffer without the - read pointer also wrapping around? */ - ulNumberOfBytesAvailable = ( unsigned long ) &( pxBuffer->pucDataBuffer[ pxBuffer->ulBufferSizeInBytes ] ) - ( unsigned long ) pxBuffer->pucNextByteToRead; - - if( ulNumberOfBytesAvailable >= ulWantedBytes ) - { - /* There is enough space from our current read pointer up to the end - of the buffer to obtain the number of bytes requested. */ - memcpy( pucBuffer, pxBuffer->pucNextByteToRead, ulWantedBytes ); - - /* Move up our read buffer. */ - pxBuffer->pucNextByteToRead += ulWantedBytes; - ulNumberOfBytesRead = ulWantedBytes; - } - else - { - /* There is not enough space up to the end of the buffer to obtain - the number of bytes requested. Copy up to the end of the buffer. */ - memcpy( pucBuffer, pxBuffer->pucNextByteToRead, ulNumberOfBytesAvailable ); - ulNumberOfBytesRead = ulNumberOfBytesAvailable; - - /* Then wrap back to the beginning of the buffer to attempt to - read the remaining bytes. */ - pxBuffer->pucNextByteToRead = pxBuffer->pucDataBuffer; - pucBuffer += ulNumberOfBytesAvailable; - - /* How many more bytes do we want to read? */ - ulWantedBytes -= ulNumberOfBytesAvailable; - - /* Clip the number of bytes we are going to read to the number - available if this is less than the number we want. */ - ulNumberOfBytesAvailable = ( unsigned long ) pucNextByteToWrite - ( unsigned long ) pxBuffer->pucNextByteToRead; - - if( ulNumberOfBytesAvailable < ulWantedBytes ) - { - ulWantedBytes = ulNumberOfBytesAvailable; - } - - /* Copy these into the buffer. */ - memcpy( pucBuffer, pxBuffer->pucNextByteToRead, ulWantedBytes ); - - /* Move up our read buffer. */ - pxBuffer->pucNextByteToRead += ulWantedBytes; - ulNumberOfBytesRead += ulWantedBytes; - } - } - - /* Check we have not moved our read pointer off the end of the buffer. */ - if( ( unsigned long ) pxBuffer->pucNextByteToRead >= ( unsigned long ) &( pxBuffer->pucDataBuffer[ pxBuffer->ulBufferSizeInBytes ] ) ) - { - pxBuffer->pucNextByteToRead = pxBuffer->pucDataBuffer; - } - - /* Return the number of bytes read. */ - return ulNumberOfBytesRead; -} - diff --git a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/CircularBuffer.h b/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/CircularBuffer.h deleted file mode 100644 index 488082824..000000000 --- a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/CircularBuffer.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd. - - *************************************************************************** - * * - * If you are: * - * * - * + New to FreeRTOS, * - * + Wanting to learn FreeRTOS or multitasking in general quickly * - * + Looking for basic training, * - * + Wanting to improve your FreeRTOS skills and productivity * - * * - * then take a look at the FreeRTOS eBook * - * * - * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * - * http://www.FreeRTOS.org/Documentation * - * * - * A pdf reference manual is also available. Both are usually delivered * - * to your inbox within 20 minutes to two hours when purchased between 8am * - * and 8pm GMT (although please allow up to 24 hours in case of * - * exceptional circumstances). Thank you for your support! * - * * - *************************************************************************** - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - ***NOTE*** The exception to the GPL is included to allow you to distribute - a combined work that includes FreeRTOS without being obliged to provide the - source code for proprietary components outside of the FreeRTOS kernel. - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#ifndef CIRCULAR_BUFFER_H -#define CIRCULAR_BUFFER_H - -/* Structure that holds the state of the circular buffer. */ -typedef struct -{ - unsigned char *pucDataBuffer; - unsigned long ulBufferSizeInBytes; - unsigned char *pucNextByteToRead; - unsigned char *pucNextByteToWrite; - unsigned long ulDataSizeInBytes; - void *pvTag; -} xCircularBuffer; - - -/* - * Setup a circular buffer ready for use. - * - * pxBuffer : The xCicularBuffer structure being initialised. - * - * pucDataBuffer : The buffer to be used by the xCicularBuffer object. - * - * ulBufferSizeInBytes : The dimention of pucDataBuffer in bytes. - * - * ulDataSizeInBytes : The size of the data that is to be stored in the - * circular buffer. For example, 4 if the buffer is used to hold - * unsigned longs, 1 if the buffer is used to hold chars. - * - * pvTag : Can be used for anything, although normally used in conjunction with - * a DMA register. - */ -void vInitialiseCircularBuffer( xCircularBuffer *pxBuffer, - unsigned char *pucDataBuffer, - unsigned long ulBufferSizeInBytes, - unsigned long ulDataSizeInBytes, - void *pvTag - ); -/* - * Returns the number of bytes that are currently available within the - * buffer. - */ -unsigned long ulBytesInCircularBuffer( const xCircularBuffer * const pxBuffer ); - -/* - * Obtain bytes from the circular buffer. Data may have been placed in - * the circular buffer by a DMA transfer or simply written to the buffer by - * the application code. - * - * pxBuffer : The circular buffer from which data is to be read. - * - * pucBuffer : The buffer into which the received bytes should be copied. - * - * ulWantedBytes : The number of bytes we are going to attempt to receive - * from the circular buffer. - * - * return : The actual number of bytes received from the circular buffer. - * This might be less than the number of bytes we attempted to receive. - */ -unsigned long ulCopyReceivedBytes( xCircularBuffer *pxBuffer, unsigned char * pucBuffer, unsigned long ulWantedBytes ); - -#endif - diff --git a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/SPI_Flash_ST_Eval.c b/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/SPI_Flash_ST_Eval.c index 6f4ba14fa..b3cfe618d 100644 --- a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/SPI_Flash_ST_Eval.c +++ b/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/SPI_Flash_ST_Eval.c @@ -15,7 +15,7 @@ *******************************************************************************/ /* Includes ------------------------------------------------------------------*/ -#include "spi_flash.h" +#include "SPI_Flash_ST_Eval.h" /* Private typedef -----------------------------------------------------------*/ #define SPI_FLASH_PageSize 0x100 diff --git a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/SPI_Flash_ST_Eval.h b/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/SPI_Flash_ST_Eval.h new file mode 100644 index 000000000..7863a1ded --- /dev/null +++ b/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/SPI_Flash_ST_Eval.h @@ -0,0 +1,75 @@ +/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +* File Name : spi_flash.h +* Author : MCD Application Team +* Version : V2.0.0 +* Date : 04/27/2009 +* Description : Header for spi_flash.c file. +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __SPI_FLASH_H +#define __SPI_FLASH_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" +#include "stm32f10x_spi.h" +#include "stm32f10x_gpio.h" +#include "stm32f10x_rcc.h" + +#define uint32_t unsigned long +#define uint8_t unsigned char +#define uint16_t unsigned short + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Uncomment the line corresponding to the STMicroelectronics evaluation board + used to run the example */ +#if !defined (USE_STM3210B_EVAL) && !defined (USE_STM3210E_EVAL) + //#define USE_STM3210B_EVAL + #define USE_STM3210E_EVAL +#endif + +#ifdef USE_STM3210B_EVAL + #define GPIO_CS GPIOA + #define RCC_APB2Periph_GPIO_CS RCC_APB2Periph_GPIOA + #define GPIO_Pin_CS GPIO_Pin_4 +#else /* USE_STM3210E_EVAL */ + #define GPIO_CS GPIOB + #define RCC_APB2Periph_GPIO_CS RCC_APB2Periph_GPIOB + #define GPIO_Pin_CS GPIO_Pin_2 +#endif + +/* Exported macro ------------------------------------------------------------*/ +/* Select SPI FLASH: Chip Select pin low */ +#define SPI_FLASH_CS_LOW() __asm volatile( "NOP" );__asm volatile( "NOP" );__asm volatile( "NOP" );__asm volatile( "NOP" );GPIO_ResetBits(GPIO_CS, GPIO_Pin_CS);__asm volatile( "NOP" );__asm volatile( "NOP" );__asm volatile( "NOP" );__asm volatile( "NOP" ) +/* Deselect SPI FLASH: Chip Select pin high */ +#define SPI_FLASH_CS_HIGH() __asm volatile( "NOP" );__asm volatile( "NOP" );__asm volatile( "NOP" );__asm volatile( "NOP" );GPIO_SetBits(GPIO_CS, GPIO_Pin_CS);__asm volatile( "NOP" );__asm volatile( "NOP" );__asm volatile( "NOP" );__asm volatile( "NOP" ) + +/* Exported functions ------------------------------------------------------- */ +/*----- High layer function -----*/ +void SPI_FLASH_Init(void); +void SPI_FLASH_SectorErase(uint32_t SectorAddr); +void SPI_FLASH_BulkErase(void); +void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); +void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); +void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead); +uint32_t SPI_FLASH_ReadID(void); +void SPI_FLASH_StartReadSequence(uint32_t ReadAddr); + +/*----- Low layer function -----*/ +uint8_t SPI_FLASH_ReadByte(void); +uint8_t SPI_FLASH_SendByte(uint8_t byte); +uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord); +void SPI_FLASH_WriteEnable(void); +void SPI_FLASH_WaitForWriteEnd(void); + +#endif /* __SPI_FLASH_H */ + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.c b/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.c index 20c0c5d46..8e978afd6 100644 --- a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.c +++ b/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.c @@ -63,15 +63,12 @@ /* Scheduler includes. */ #include "FreeRTOS.h" +#include "task.h" #include "queue.h" #include "semphr.h" -/* Driver includes. */ -#include "CircularBuffer.h" - /* Library includes. */ #include "stm32f10x_lib.h" -#include "stm32f10x_rcc.h" /* Driver includes. */ #include "STM32_USART.h" @@ -80,40 +77,43 @@ /* The number of COM ports that can be controlled at the same time. */ #define serNUM_COM_PORTS ( 2 ) -/* Indexes into the xCOMBufferDefinitions array for the Rx and Tx buffers. */ -#define serRX_BUFFER_INDEX ( 0 ) -#define serTX_BUFFER_INDEX ( 1 ) +/* Queues are used to hold characters that are waiting to be transmitted. This +constant sets the maximum number of characters that can be contained in such a +queue at any one time. */ +#define serTX_QUEUE_LEN ( 100 ) + +/* Queues are used to hold characters that have been received but not yet +processed. This constant sets the maximum number of characters that can be +contained in such a queue. */ +#define serRX_QUEUE_LEN ( 100 ) -/* A counting semaphore is used to allows tasks to block to wait for characters -to be received. This constant defines the max count. Making this value higher -does not change the amount of RAM used by the semaphore, so its worth making it -quite high. */ -#define serSEMAPHORE_MAX_COUNT ( 100 ) +/* The maximum amount of time that calls to lSerialPutString() should wait for +there to be space to post each character to the queue of characters waiting +transmission. NOTE! This is the time to wait per character - not the time to +wait for the entire string. */ +#define serPUT_STRING_CHAR_DELAY ( 5 / portTICK_RATE_MS ) /*-----------------------------------------------------------*/ -/* An Rx and a Tx buffer structure for each COM port. */ -static xCircularBuffer xCOMBufferDefinitions[ serNUM_COM_PORTS ][ 2 ]; +/* References to the USART peripheral addresses themselves. */ +static USART_TypeDef * const xUARTS[ serNUM_COM_PORTS ] = { ( ( USART_TypeDef * ) USART1_BASE ), ( ( USART_TypeDef * ) USART2_BASE ) }; -/* The buffers themselves. */ -static unsigned char ucCOM0_Rx_Buffer[ configCOM0_RX_BUFFER_LENGTH ]; -static unsigned char ucCOM0_Tx_Buffer[ configCOM0_TX_BUFFER_LENGTH ]; -static unsigned char ucCOM1_Rx_Buffer[ configCOM1_RX_BUFFER_LENGTH ]; -static unsigned char ucCOM1_Tx_Buffer[ configCOM1_TX_BUFFER_LENGTH ]; +/* Queues used to hold characters waiting to be transmitted - one queue per port. */ +static xQueueHandle xCharsForTx[ serNUM_COM_PORTS ] = { 0 }; -/* Semaphores used to block tasks that are waiting for characters to be -received. */ -static xSemaphoreHandle xCOM0RxSemaphore, xCOM1RxSemaphore; +/* Queues holding received characters - one queue per port. */ +static xQueueHandle xRxedChars[ serNUM_COM_PORTS ] = { 0 }; /*-----------------------------------------------------------*/ -/* UART interrupt handler. */ -void vUARTInterruptHandler( void ); +/* UART interrupt handlers, as named in the vector table. */ +void USART1_IRQHandler( void ); +void USART2_IRQHandler( void ); /*-----------------------------------------------------------*/ /* - * See serial.h in this project for parameter descriptions. + * See header file for parameter descriptions. */ long lCOMPortInit( unsigned long ulPort, unsigned long ulWantedBaud ) { @@ -141,26 +141,13 @@ GPIO_InitTypeDef GPIO_InitStructure; does not check to see if the COM port has already been initialised. */ if( ulPort == 0 ) { - /* Create the semaphore used to enable tasks to block to wait for - characters to be received. */ - xCOM0RxSemaphore = xSemaphoreCreateCounting( serSEMAPHORE_MAX_COUNT, 0 ); - - vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serRX_BUFFER_INDEX ] ), - ucCOM0_Rx_Buffer, - configCOM0_RX_BUFFER_LENGTH, - sizeof( unsigned char ), - NULL - ); - - vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serTX_BUFFER_INDEX ] ), - ucCOM0_Tx_Buffer, - configCOM0_TX_BUFFER_LENGTH, - sizeof( unsigned char ), - NULL - ); - - /* Enable COM1 clock - the ST libraries start numbering from UART1, - making this UART 2. */ + /* Create the queue of chars that are waiting to be sent to COM0. */ + xCharsForTx[ 0 ] = xQueueCreate( serTX_QUEUE_LEN, sizeof( char ) ); + + /* Create the queue used to hold characters received from COM0. */ + xRxedChars[ 0 ] = xQueueCreate( serRX_QUEUE_LEN, sizeof( char ) ); + + /* Enable COM0 clock - the ST libraries start numbering from UART1. */ RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE ); /* Configure USART1 Rx (PA10) as input floating */ @@ -182,26 +169,17 @@ GPIO_InitTypeDef GPIO_InitStructure; USART_DMACmd( USART1, ( USART_DMAReq_Tx | USART_DMAReq_Rx ), ENABLE ); USART_Cmd( USART1, ENABLE ); + + /* Everything is ok. */ + lReturn = pdPASS; } - else + else if( ulPort == 1 ) { - /* Create the semaphore used to enable tasks to block to wait for - characters to be received. */ - xCOM1RxSemaphore = xSemaphoreCreateCounting( serSEMAPHORE_MAX_COUNT, 0 ); - - vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serRX_BUFFER_INDEX ] ), - ucCOM1_Rx_Buffer, - configCOM1_RX_BUFFER_LENGTH, - sizeof( unsigned char ), - NULL - ); - - vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serTX_BUFFER_INDEX ] ), - ucCOM1_Tx_Buffer, - configCOM1_TX_BUFFER_LENGTH, - sizeof( unsigned char ), - NULL - ); + /* Create the queue of chars that are waiting to be sent to COM1. */ + xCharsForTx[ 1 ] = xQueueCreate( serTX_QUEUE_LEN, sizeof( char ) ); + + /* Create the queue used to hold characters received from COM0. */ + xRxedChars[ 1 ] = xQueueCreate( serRX_QUEUE_LEN, sizeof( char ) ); /* Enable COM0 clock - the ST libraries start numbering from 1. */ RCC_APB2PeriphClockCmd( RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOA, ENABLE ); @@ -225,34 +203,89 @@ GPIO_InitTypeDef GPIO_InitStructure; USART_DMACmd( USART2, ( USART_DMAReq_Tx | USART_DMAReq_Rx ), ENABLE ); USART_Cmd( USART2, ENABLE ); + + /* Everything is ok. */ + lReturn = pdPASS; } - - /* Everything is ok. */ - lReturn = pdPASS; + else + { + /* Nothing to do unless more than two ports are supported. */ + } } return lReturn; } /*-----------------------------------------------------------*/ -signed long xUSARTGetChar( long lPort, signed char *pcRxedChar, portTickType xBlockTime ) +signed long xSerialGetChar( long lPort, signed char *pcRxedChar, portTickType xBlockTime ) { - return pdFALSE; +long lReturn = pdFAIL; + + if( lPort < serNUM_COM_PORTS ) + { + if( xQueueReceive( xRxedChars[ lPort ], pcRxedChar, xBlockTime ) == pdPASS ) + { + lReturn = pdPASS; + } + } + + return lReturn; } /*-----------------------------------------------------------*/ -void vSerialPutString( long lPort, const signed char * const pcString, unsigned portSHORT usStringLength ) +long lSerialPutString( long lPort, const char * const pcString, unsigned long ulStringLength ) { +long lReturn; +unsigned long ul; + + if( lPort < serNUM_COM_PORTS ) + { + lReturn = pdPASS; + + for( ul = 0; ul < ulStringLength; ul++ ) + { + if( xQueueSend( xCharsForTx[ lPort ], &( pcString[ ul ] ), serPUT_STRING_CHAR_DELAY ) != pdPASS ) + { + /* Cannot fit any more in the queue. Try turning the Tx on to + clear some space. */ + USART_ITConfig( xUARTS[ lPort ], USART_IT_TXE, ENABLE ); + vTaskDelay( serPUT_STRING_CHAR_DELAY ); + + /* Go back and try again. */ + continue; + } + } + + USART_ITConfig( xUARTS[ lPort ], USART_IT_TXE, ENABLE ); + } + else + { + lReturn = pdFAIL; + } + + return lReturn; } /*-----------------------------------------------------------*/ signed long xSerialPutChar( long lPort, signed char cOutChar, portTickType xBlockTime ) { - return pdFALSE; +long lReturn; + + if( xQueueSend( xCharsForTx[ lPort ], &cOutChar, xBlockTime ) == pdPASS ) + { + lReturn = pdPASS; + USART_ITConfig( xUARTS[ lPort ], USART_IT_TXE, ENABLE ); + } + else + { + lReturn = pdFAIL; + } + + return lReturn; } /*-----------------------------------------------------------*/ -void vUARTInterruptHandler( void ) +void USART1_IRQHandler( void ) { long xHigherPriorityTaskWoken = pdFALSE; char cChar; @@ -261,9 +294,9 @@ char cChar; { /* The interrupt was caused by the THR becoming empty. Are there any more characters to transmit? */ -if( 0 )// if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE ) + if( xQueueReceiveFromISR( xCharsForTx[ 0 ], &cChar, &xHigherPriorityTaskWoken ) ) { - /* A character was retrieved from the queue so can be sent to the + /* A character was retrieved from the buffer so can be sent to the THR now. */ USART_SendData( USART1, cChar ); } @@ -276,12 +309,16 @@ if( 0 )// if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWo if( USART_GetITStatus( USART1, USART_IT_RXNE ) == SET ) { cChar = USART_ReceiveData( USART1 ); -// xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken ); + xQueueSendFromISR( xRxedChars[ 0 ], &cChar, &xHigherPriorityTaskWoken ); } portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); } +/*-----------------------------------------------------------*/ +void USART2_IRQHandler( void ) +{ +} diff --git a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.h b/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.h index 9ef0cd66d..898835b3c 100644 --- a/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.h +++ b/Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.h @@ -55,6 +55,9 @@ #define STM_32_SERIAL_COMMS_H long lCOMPortInit( unsigned long ulPort, unsigned long ulWantedBaud ); +signed long xSerialPutChar( long lPort, signed char cOutChar, portTickType xBlockTime ); +signed long xSerialGetChar( long lPort, signed char *pcRxedChar, portTickType xBlockTime ); +long lSerialPutString( long lPort, const char * const pcString, unsigned long ulStringLength ); #endif diff --git a/Demo/CORTEX_STM32F103_GCC_Rowley/RTOSDemo.hzp b/Demo/CORTEX_STM32F103_GCC_Rowley/RTOSDemo.hzp index 446f0dc1c..c2850ec85 100644 --- a/Demo/CORTEX_STM32F103_GCC_Rowley/RTOSDemo.hzp +++ b/Demo/CORTEX_STM32F103_GCC_Rowley/RTOSDemo.hzp @@ -1,7 +1,7 @@ - + @@ -36,14 +36,16 @@ - + + + + - diff --git a/Demo/CORTEX_STM32F103_GCC_Rowley/RTOSDemo.hzs b/Demo/CORTEX_STM32F103_GCC_Rowley/RTOSDemo.hzs index 53fa2ecde..60c0db1fb 100644 --- a/Demo/CORTEX_STM32F103_GCC_Rowley/RTOSDemo.hzs +++ b/Demo/CORTEX_STM32F103_GCC_Rowley/RTOSDemo.hzs @@ -18,10 +18,6 @@ - - - - @@ -53,11 +49,14 @@ - - - - - + + + + + + + + - + diff --git a/Demo/CORTEX_STM32F103_GCC_Rowley/main.c b/Demo/CORTEX_STM32F103_GCC_Rowley/main.c index ba3761bc4..fda780811 100644 --- a/Demo/CORTEX_STM32F103_GCC_Rowley/main.c +++ b/Demo/CORTEX_STM32F103_GCC_Rowley/main.c @@ -61,27 +61,28 @@ * In addition to the standard demo tasks, the following tasks and tests are * defined and/or created within this file: * - * "Check" task - This only executes every five seconds but has the highest + * "Check" task - This only executes every five seconds but has the highest * priority so is guaranteed to get processor time. Its main function is to * check that all the standard demo tasks are still operational. The check task - * will toggle LED 7 (PB15) every five seconds so long as no errors have been + * will toggle LED 3 (PB11) every five seconds so long as no errors have been * detected. The toggle rate will increase to half a second if an error has * been found in any task. * + * "Echo" task - This is a very basic task that simply echoes any characters + * received on COM0 (USART1). This can be tested by transmitting a text file + * from a dumb terminal to the STM32 USART. */ /* Standard includes. */ -#include +#include /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" #include "queue.h" -#include "semphr.h" /* Library includes. */ #include "stm32f10x_it.h" -#include "stm32f10x_tim.h" /* Demo app includes. */ #include "BlockQ.h" @@ -93,6 +94,9 @@ #include "QPeek.h" #include "recmutex.h" +/* Driver includes. */ +#include "STM32_USART.h" + /* The time between cycles of the 'check' task - which depends on whether the check task has detected an error or not. */ @@ -107,9 +111,14 @@ check task has detected an error or not. */ #define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) #define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define mainECHO_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY ) #define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY ) +/* COM port and baud rate used by the echo task. */ +#define mainCOM0 ( 0 ) +#define mainBAUD_RATE ( 115200 ) + /*-----------------------------------------------------------*/ /* @@ -120,6 +129,10 @@ static void prvSetupHardware( void ); /* The 'check' task as described at the top of this file. */ static void prvCheckTask( void *pvParameters ); +/* A simple task that echoes all the characters that are received on COM0 +(USART1). */ +static void prvUSARTEchoTask( void *pvParameters ); + /*-----------------------------------------------------------*/ int main( void ) @@ -141,7 +154,10 @@ int main( void ) vStartQueuePeekTasks(); vStartRecursiveMutexTasks(); - /* Create the 'check' task, which is defined within this file. */ + /* Create the 'echo' task, which is also defined within this file. */ + xTaskCreate( prvUSARTEchoTask, ( signed char * ) "Echo", configMINIMAL_STACK_SIZE, NULL, mainECHO_TASK_PRIORITY, NULL ); + + /* Create the 'check' task, which is also defined within this file. */ xTaskCreate( prvCheckTask, ( signed char * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); /* Start the scheduler. */ @@ -153,6 +169,7 @@ int main( void ) } /*-----------------------------------------------------------*/ +/* Described at the top of this file. */ static void prvCheckTask( void *pvParameters ) { portTickType xLastExecutionTime; @@ -204,6 +221,49 @@ unsigned long ulTicksToWait = mainCHECK_DELAY_NO_ERROR; } /*-----------------------------------------------------------*/ +/* Described at the top of this file. */ +static void prvUSARTEchoTask( void *pvParameters ) +{ +signed char cChar; + +/* String declared static to ensure it does not end up on the stack, no matter +what the optimisation level. */ +static const char *pcLongishString = +"ABBA was a Swedish pop music group formed in Stockholm in 1972, consisting of Anni-Frid Frida Lyngstad, " +"Björn Ulvaeus, Benny Andersson and Agnetha Fältskog. Throughout the band's existence, Fältskog and Ulvaeus " +"were a married couple, as were Lyngstad and Andersson - although both couples later divorced. They became one " +"of the most commercially successful acts in the history of popular music, and they topped the charts worldwide " +"from 1972 to 1983. ABBA gained international popularity employing catchy song hooks, simple lyrics, sound " +"effects (reverb, phasing) and a Wall of Sound achieved by overdubbing the female singers' voices in multiple " +"harmonies. As their popularity grew, they were sought after to tour Europe, Australia, and North America, drawing " +"crowds of ardent fans, notably in Australia. Touring became a contentious issue, being particularly cumbersome for " +"Fältskog, but they continued to release studio albums to widespread commercial success. At the height of their " +"popularity, however, both relationships began suffering strain that led ultimately to the collapse of first the " +"Ulvaeus-Fältskog marriage (in 1979) and then of the Andersson-Lyngstad marriage in 1981. In the late 1970s and early " +"1980s these relationship changes began manifesting in the group's music, as they produced more thoughtful, " +"introspective lyrics with different compositions."; + + /* Just to avoid compiler warnings. */ + ( void ) pvParameters; + + /* Initialise COM0, which is USART1 according to the STM32 libraries. */ + lCOMPortInit( mainCOM0, mainBAUD_RATE ); + + /* Try sending out a string all in one go, as a very basic test of the + lSerialPutString() function. */ + lSerialPutString( mainCOM0, pcLongishString, strlen( pcLongishString ) ); + + for( ;; ) + { + /* Block to wait for a character to be received on COM0. */ + xSerialGetChar( mainCOM0, &cChar, portMAX_DELAY ); + + /* Write the received character back to COM0. */ + xSerialPutChar( mainCOM0, cChar, 0 ); + } +} +/*-----------------------------------------------------------*/ + static void prvSetupHardware( void ) { /* RCC system reset(for debug purpose). */ @@ -262,9 +322,6 @@ static void prvSetupHardware( void ) /* SPI2 Periph clock enable */ RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE ); - - /* Initialize the SPI FLASH driver */ - SPI_FLASH_Init(); } /*-----------------------------------------------------------*/ diff --git a/Demo/CORTEX_STM32F103_GCC_Rowley/stm32f10x_conf.h b/Demo/CORTEX_STM32F103_GCC_Rowley/stm32f10x_conf.h index 4baed96ec..7d064c243 100644 --- a/Demo/CORTEX_STM32F103_GCC_Rowley/stm32f10x_conf.h +++ b/Demo/CORTEX_STM32F103_GCC_Rowley/stm32f10x_conf.h @@ -114,7 +114,7 @@ /************************************* SPI ************************************/ #define _SPI #define _SPI1 -//#define _SPI2 +#define _SPI2 //#define _SPI3 /************************************* SysTick ********************************/ -- 2.39.2