From 0fd4deb72cda7952d076dbc6b903ba0f910c2eb2 Mon Sep 17 00:00:00 2001 From: richardbarry Date: Sat, 1 Jan 2011 11:27:48 +0000 Subject: [PATCH] Prepare the MSP430X IAR demo for release. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1202 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Demo/MSP430X_MSP430F5438_IAR/FreeRTOSConfig.h | 11 +- .../MSP-EXP430F5438_HAL/hal_lcd.c | 762 +++++++++--------- Demo/MSP430X_MSP430F5438_IAR/ParTest.c | 8 + Demo/MSP430X_MSP430F5438_IAR/RTOSDemo.ewp | 3 + Demo/MSP430X_MSP430F5438_IAR/RegTest.s43 | 72 +- .../RunTimeStatsConfig.c | 115 +++ .../lnk430F5438A_mod.xcl | 4 +- Demo/MSP430X_MSP430F5438_IAR/main.c | 291 ++++--- Demo/MSP430X_MSP430F5438_IAR/serial.c | 27 +- .../settings/RTOSDemo.dbgdt | 12 +- .../settings/RTOSDemo.dni | 14 +- .../settings/RTOSDemo.wsdt | 8 +- 12 files changed, 796 insertions(+), 531 deletions(-) create mode 100644 Demo/MSP430X_MSP430F5438_IAR/RunTimeStatsConfig.c diff --git a/Demo/MSP430X_MSP430F5438_IAR/FreeRTOSConfig.h b/Demo/MSP430X_MSP430F5438_IAR/FreeRTOSConfig.h index c7bb39210..45a9615b1 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/FreeRTOSConfig.h +++ b/Demo/MSP430X_MSP430F5438_IAR/FreeRTOSConfig.h @@ -74,7 +74,7 @@ #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 10 * 1024 ) ) -#define configMAX_TASK_NAME_LEN ( 16 ) +#define configMAX_TASK_NAME_LEN ( 10 ) #define configUSE_TRACE_FACILITY 0 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 @@ -92,15 +92,20 @@ /* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */ - #define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_uxTaskPriorityGet 1 -#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskDelete 0 #define INCLUDE_vTaskCleanUpResources 0 #define INCLUDE_vTaskSuspend 1 #define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelay 1 +/* The MSP430X port uses a callback function to configure its tick interrupt. +This allows the application to choose the tick interrupt source. +configTICK_INTERRUPT_VECTOR must also be set in FreeRTOSConfig.h to the correct +interrupt vector for the chosen tick interrupt source. This implementation of +vApplicationSetupTimerInterrupt() generates the tick from timer A0, so in this +case configTICK_INTERRUPT_VECTOR is set to TIMER0_A0_VECTOR. */ #define configTICK_INTERRUPT_VECTOR TIMER0_A0_VECTOR /* Prevent the following definitions being included when FreeRTOSConfig.h diff --git a/Demo/MSP430X_MSP430F5438_IAR/MSP-EXP430F5438_HAL/hal_lcd.c b/Demo/MSP430X_MSP430F5438_IAR/MSP-EXP430F5438_HAL/hal_lcd.c index 12c611ed7..f589c23dd 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/MSP-EXP430F5438_HAL/hal_lcd.c +++ b/Demo/MSP430X_MSP430F5438_IAR/MSP-EXP430F5438_HAL/hal_lcd.c @@ -1,6 +1,6 @@ -/** +/** * @file hal_lcd.c - * + * * Copyright 2010 Texas Instruments, Inc. ***************************************************************************/ @@ -19,88 +19,88 @@ unsigned char LcdInitMacro[]={ 0x74,0x00,0x07,0x76,0x00,0x15, // R07 Display control 0x74,0x00,0x08,0x76,0x00,0x03, // R08 Cursor Control 0x74,0x00,0x09,0x76,0x00,0x00, // R09 RAM data write mask - 0x74,0x00,0x0A,0x76,0x00,0x15, // R0A + 0x74,0x00,0x0A,0x76,0x00,0x15, // R0A 0x74,0x00,0x0B,0x76,0x00,0x03, // R0B Horizontal Cursor Position 0x74,0x00,0x0C,0x76,0x00,0x03, // R0C Vertical Cursor Position - 0x74,0x00,0x0D,0x76,0x00,0x00, // R0D - 0x74,0x00,0x0E,0x76,0x00,0x15, // R0E - 0x74,0x00,0x0F,0x76,0x00,0x03, // R0F - 0x74,0x00,0x10,0x76,0x00,0x15, // R0E - 0x74,0x00,0x11,0x76,0x00,0x03, // R0F + 0x74,0x00,0x0D,0x76,0x00,0x00, // R0D + 0x74,0x00,0x0E,0x76,0x00,0x15, // R0E + 0x74,0x00,0x0F,0x76,0x00,0x03, // R0F + 0x74,0x00,0x10,0x76,0x00,0x15, // R0E + 0x74,0x00,0x11,0x76,0x00,0x03, // R0F }; -unsigned char Read_Block_Address_Macro[]= {0x74,0x00,0x12,0x77,0x00,0x00}; +unsigned char Read_Block_Address_Macro[]= {0x74,0x00,0x12,0x77,0x00,0x00}; unsigned char Draw_Block_Value_Macro[]={0x74,0x00,0x12,0x76,0xFF,0xFF}; unsigned char Draw_Block_Address_Macro[]={0x74,0x00,0x11,0x76,0x00,0x00}; unsigned int LcdAddress = 0, LcdTableAddress = 0; unsigned char contrast = 0x66; unsigned char backlight = 8; -int LCD_MEM[110*17]; //This array stores a copy of all data on the LCD - //screen. If memory is an issue though, this array +int LCD_MEM[110*17]; //This array stores a copy of all data on the LCD + //screen. If memory is an issue though, this array //can be eliminated and the halLcdReadBlock() - //command can be used instead whenever you are + //command can be used instead whenever you are //manipulating the currently displayed data. /**********************************************************************//** * @brief Sends 3+3 bytes of data to the LCD using the format specified * by the LCD Guide. - * - * @param Data[] Data array for transmission - * + * + * @param Data[] Data array for transmission + * * @return none *************************************************************************/ -void halLcdSendCommand(unsigned char Data[]) +void halLcdSendCommand(unsigned char Data[]) { unsigned char i; LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer for ( i = 0; i < 6; i++ ) { - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG - UCB2TXBUF = Data[i]; // Load data + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + UCB2TXBUF = Data[i]; // Load data if (i == 2) //Pull CS up after 3 bytes { while (UCB2STAT & UCBUSY); LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer - LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer + LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer } } while (UCB2STAT & UCBUSY); - LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer + LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer } /**********************************************************************//** - * @brief Initializes the USCI module, LCD device for communication. - * + * @brief Initializes the USCI module, LCD device for communication. + * * - Sets up the SPI2C Communication Module * - Performs Hitachi LCD Initialization Procedure - * + * * @param none - * + * * @return none *************************************************************************/ -void halLcdInit(void) +void halLcdInit(void) { volatile unsigned int i=0; LCD_CS_RST_OUT |= LCD_CS_PIN | LCD_RESET_PIN ; - LCD_CS_RST_DIR |= LCD_CS_PIN | LCD_RESET_PIN ; + LCD_CS_RST_DIR |= LCD_CS_PIN | LCD_RESET_PIN ; LCD_BACKLT_SEL |= LCD_BACKLIGHT_PIN; LCD_CS_RST_OUT &= ~LCD_RESET_PIN; // Reset LCD __delay_cycles(0x47FF); //Reset Pulse - LCD_CS_RST_OUT |= LCD_RESET_PIN; + LCD_CS_RST_OUT |= LCD_RESET_PIN; // UCLK,MOSI setup, SOMI cleared LCD_SPI_SEL |= LCD_MOSI_PIN + LCD_CLK_PIN; LCD_SPI_SEL &= ~LCD_MISO_PIN; LCD_SPI_DIR &= ~(LCD_MISO_PIN + LCD_MOSI_PIN); // Pin direction controlled by module, // Set both pins to input as default - - // Initialize the USCI_B2 module for SPI operation + + // Initialize the USCI_B2 module for SPI operation UCB2CTL1 = UCSWRST; // Hold USCI in SW reset mode while configuring it UCB2CTL0 = UCMST+UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI master UCB2CTL1 |= UCSSEL_2; // SMCLK @@ -111,7 +111,7 @@ void halLcdInit(void) // Wake-up the LCD as per datasheet specifications halLcdActive(); - + // LCD Initialization Routine Using Predefined Macros halLcdSendCommand(&LcdInitMacro[ 1 * 6 ]); halLcdSendCommand(&LcdInitMacro[ 2 * 6 ]); @@ -123,122 +123,122 @@ void halLcdInit(void) } /**********************************************************************//** - * @brief Shuts down the LCD display and hdisables the USCI communication. - * + * @brief Shuts down the LCD display and hdisables the USCI communication. + * * @param none - * + * * @return none *************************************************************************/ void halLcdShutDown(void) { - halLcdStandby(); + halLcdStandby(); LCD_CS_RST_DIR |= LCD_CS_PIN | LCD_RESET_PIN ; - LCD_CS_RST_OUT &= ~(LCD_CS_PIN | LCD_RESET_PIN ); - LCD_CS_RST_OUT &= ~LCD_RESET_PIN; - + LCD_CS_RST_OUT &= ~(LCD_CS_PIN | LCD_RESET_PIN ); + LCD_CS_RST_OUT &= ~LCD_RESET_PIN; + LCD_SPI_SEL &= ~(LCD_MOSI_PIN + LCD_CLK_PIN + LCD_MISO_PIN); LCD_CS_RST_DIR |= LCD_MOSI_PIN + LCD_CLK_PIN + LCD_MISO_PIN; - LCD_CS_RST_OUT &= ~(LCD_MOSI_PIN + LCD_CLK_PIN + LCD_MISO_PIN); - - UCB2CTL0 = UCSWRST; -} + LCD_CS_RST_OUT &= ~(LCD_MOSI_PIN + LCD_CLK_PIN + LCD_MISO_PIN); + + UCB2CTL0 = UCSWRST; +} /**********************************************************************//** - * @brief Initializes the LCD backlight PWM signal. - * + * @brief Initializes the LCD backlight PWM signal. + * * @param none - * + * * @return none - * + * *************************************************************************/ void halLcdBackLightInit(void) { LCD_BACKLT_DIR |= LCD_BACKLIGHT_PIN; - LCD_BACKLT_OUT |= LCD_BACKLIGHT_PIN; + LCD_BACKLT_OUT |= LCD_BACKLIGHT_PIN; LCD_BACKLT_SEL |= LCD_BACKLIGHT_PIN; TA0CCTL3 = OUTMOD_7; TA0CCR3 = TA0CCR0 >> 1 ; backlight = 8; - + TA0CCR0 = 400; - TA0CTL = TASSEL_2+MC_1; + TA0CTL = TASSEL_2+MC_1; } /**********************************************************************//** - * @brief Get function for the backlight PWM's duty cycle. - * - * @param none - * - * @return backlight One of the the 17 possible settings - valued 0 to 16. + * @brief Get function for the backlight PWM's duty cycle. + * + * @param none + * + * @return backlight One of the the 17 possible settings - valued 0 to 16. * *************************************************************************/ unsigned int halLcdGetBackLight(void) -{ +{ return backlight; } /**********************************************************************//** - * @brief Set function for the backlight PWM's duty cycle - * + * @brief Set function for the backlight PWM's duty cycle + * * @param BackLightLevel The target backlight duty cycle - valued 0 to 16. - * + * * @return none *************************************************************************/ void halLcdSetBackLight(unsigned char BackLightLevel) -{ - unsigned int dutyCycle = 0, i, dummy; - +{ + unsigned int dutyCycle = 0, i, dummy; + if (BackLightLevel > 0) { TA0CCTL3 = OUTMOD_7; dummy = (TA0CCR0 >> 4); - - for (i = 0; i < BackLightLevel; i++) + + for (i = 0; i < BackLightLevel; i++) dutyCycle += dummy; - + TA0CCR3 = dutyCycle; - - // If the backlight was previously turned off, turn it on. - if (!backlight) - TA0CTL |= MC0; + + // If the backlight was previously turned off, turn it on. + if (!backlight) + TA0CTL |= MC0; } else { TA0CCTL3 = 0; TA0CTL &= ~MC0; - } + } backlight = BackLightLevel; } /**********************************************************************//** - * @brief Turns off the backlight. - * + * @brief Turns off the backlight. + * * Clears the respective GPIO and timer settings. - * + * * @param none - * + * * @return none *************************************************************************/ void halLcdShutDownBackLight(void) { LCD_BACKLT_DIR |= LCD_BACKLIGHT_PIN; - LCD_BACKLT_OUT &= ~(LCD_BACKLIGHT_PIN); + LCD_BACKLT_OUT &= ~(LCD_BACKLIGHT_PIN); LCD_BACKLT_SEL &= ~LCD_BACKLIGHT_PIN; - + TA0CCTL3 = 0; - TA0CTL = 0; - - backlight = 0; + TA0CTL = 0; + + backlight = 0; } /**********************************************************************//** - * @brief Set function for the contrast level of the LCD. - * - * @param ContrastLevel The target contrast level - * - * @return none + * @brief Set function for the contrast level of the LCD. + * + * @param ContrastLevel The target contrast level + * + * @return none *************************************************************************/ void halLcdSetContrast(unsigned char ContrastLevel) { @@ -246,13 +246,13 @@ void halLcdSetContrast(unsigned char ContrastLevel) if (ContrastLevel < 70) ContrastLevel = 70; LcdInitMacro[ 0x04 * 6 + 5 ] = ContrastLevel; halLcdSendCommand(&LcdInitMacro[ 0x04 * 6 ]); -} +} /**********************************************************************//** - * @brief Get function for the contrast level of the LCD. - * + * @brief Get function for the contrast level of the LCD. + * * @param none - * + * * @return ContrastLevel The LCD constrast level *************************************************************************/ unsigned char halLcdGetContrast(void) @@ -262,31 +262,31 @@ unsigned char halLcdGetContrast(void) /**********************************************************************//** * @brief Turns the LCD cursor on at the current text position. - * + * * @param none - * + * * @return none *************************************************************************/ void halLcdCursor(void) { LcdInitMacro[ 8 * 6 + 5 ] ^= BIT2; halLcdSendCommand(&LcdInitMacro[ 8 * 6 ]); - + LcdInitMacro[ 0x0B * 6 + 5 ] = ((LcdAddress & 0x1F) << 3) ; LcdInitMacro[ 0x0B * 6 + 4 ] = ( (LcdAddress & 0x1F) << 3 ) + 3; LcdInitMacro[ 0x0C * 6 + 5 ] = (LcdAddress >> 5); LcdInitMacro[ 0x0C * 6 + 4 ] = (LcdAddress >> 5) + 7; halLcdSendCommand(&LcdInitMacro[ 0x0B * 6 ]); halLcdSendCommand(&LcdInitMacro[ 0x0C * 6 ]); - + halLcdSetAddress(LcdAddress); } /**********************************************************************//** * @brief Turns off the LCD cursor. - * + * * @param none - * + * * @return none *************************************************************************/ void halLcdCursorOff(void) @@ -296,10 +296,10 @@ void halLcdCursorOff(void) } /**********************************************************************//** - * @brief Inverts the grayscale values of the LCD display (Black <> white). - * + * @brief Inverts the grayscale values of the LCD display (Black <> white). + * * @param none - * + * * @return none *************************************************************************/ void halLcdReverse(void) @@ -310,9 +310,9 @@ void halLcdReverse(void) /**********************************************************************//** * @brief Sets the LCD in standby mode to reduce power consumption. - * + * * @param none - * + * * @return none *************************************************************************/ void halLcdStandby(void) @@ -324,60 +324,60 @@ void halLcdStandby(void) /**********************************************************************//** * @brief Puts the LCD into active mode. - * + * * @param none - * + * * @return none *************************************************************************/ void halLcdActive(void) { halLcdSendCommand(LcdInitMacro); // R00 start oscillation - + // Wait a minimum of 25ms after issuing "start oscillation" - // command (to accomodate for MCLK up to 25MHz) - __delay_cycles(250000); - + // command (to accomodate for MCLK up to 25MHz) + __delay_cycles(250000); + LcdInitMacro[ 3 * 6 + 5 ] |= BIT3; LcdInitMacro[ 3 * 6 + 5 ] &= ~BIT0; halLcdSendCommand(&LcdInitMacro[ 3 * 6 ]); // R03 Power control } /**********************************************************************//** - * @brief Sets the pointer location in the LCD. - * - * - LcdAddress = Address - * - LcdTableAddress = Correct Address Row + Column - * = (Address / 0x20)* 17 + Column - * + * @brief Sets the pointer location in the LCD. + * + * - LcdAddress = Address + * - LcdTableAddress = Correct Address Row + Column + * = (Address / 0x20)* 17 + Column + * * @param Address The target pointer location in the LCD. - * + * * @return none *************************************************************************/ void halLcdSetAddress(int Address) { int temp; - + Draw_Block_Address_Macro[4] = Address >> 8; Draw_Block_Address_Macro[5] = Address & 0xFF; halLcdSendCommand(Draw_Block_Address_Macro); LcdAddress = Address; temp = Address >> 5; // Divided by 0x20 - temp = temp + (temp << 4); + temp = temp + (temp << 4); //Multiplied by (1+16) and added by the offset - LcdTableAddress = temp + (Address & 0x1F); + LcdTableAddress = temp + (Address & 0x1F); } /**********************************************************************//** - * @brief Draws a block at the specified LCD address. - * + * @brief Draws a block at the specified LCD address. + * * A block is the smallest addressable memory on the LCD and is * equivalent to 8 pixels, each of which is represented by 2 bits - * that represent a grayscale value between 00b and 11b. - * + * that represent a grayscale value between 00b and 11b. + * * @param Address The address at which to draw the block. - * - * @param Value The value of the block - * + * + * @param Value The value of the block + * * @return none *************************************************************************/ void halLcdDrawBlock(unsigned int Address, unsigned int Value) @@ -387,182 +387,182 @@ void halLcdDrawBlock(unsigned int Address, unsigned int Value) } /**********************************************************************//** - * @brief Writes Value to LCD CGram and MSP430 internal LCD table. - * + * @brief Writes Value to LCD CGram and MSP430 internal LCD table. + * * Also updates the LcdAddress and LcdTableAddress to the correct values. - * - * @param Value The value of the block to be written to the LCD. - * + * + * @param Value The value of the block to be written to the LCD. + * * @return none *************************************************************************/ void halLcdDrawCurrentBlock(unsigned int Value) -{ +{ int temp; Draw_Block_Value_Macro[4] = Value >> 8; Draw_Block_Value_Macro[5] = Value & 0xFF; LCD_MEM[ LcdTableAddress ] = Value; - + halLcdSendCommand(Draw_Block_Value_Macro); - + LcdAddress++; temp = LcdAddress >> 5; // Divided by 0x20 - temp = temp + (temp << 4); + temp = temp + (temp << 4); // Multiplied by (1+16) and added by the offset - LcdTableAddress = temp + (LcdAddress & 0x1F); - + LcdTableAddress = temp + (LcdAddress & 0x1F); + // If LcdAddress gets off the right edge, move to next line if ((LcdAddress & 0x1F) > 0x11) halLcdSetAddress( (LcdAddress & 0xFFE0) + 0x20 ); if (LcdAddress == LCD_Size) - halLcdSetAddress( 0 ); + halLcdSetAddress( 0 ); } /**********************************************************************//** * @brief Returns the LCD CGRAM value at location Address. - * - * @param Address The address of the block to be read from the LCD. - * + * + * @param Address The address of the block to be read from the LCD. + * * @return Value The value held at the specified address. *************************************************************************/ int halLcdReadBlock(unsigned int Address) { - int i = 0, Value = 0, ReadData[7]; - - halLcdSetAddress( Address ); - halLcdSendCommand(Read_Block_Address_Macro); - + int i = 0, Value = 0, ReadData[7]; + + halLcdSetAddress( Address ); + halLcdSendCommand(Read_Block_Address_Macro); + LCD_CS_RST_OUT &= ~LCD_CS_PIN; // start transfer CS=0 UCB2TXBUF = 0x77; // Transmit first character 0x77 - - while (!(UCB2IFG & UCTXIFG)); + + while (!(UCB2IFG & UCTXIFG)); while (UCB2STAT & UCBUSY); - - //Read 5 dummies values and 2 valid address data + + //Read 5 dummies values and 2 valid address data LCD_SPI_SEL &= ~LCD_MOSI_PIN; //Change SPI2C Dir - LCD_SPI_SEL |= LCD_MISO_PIN; - + LCD_SPI_SEL |= LCD_MISO_PIN; + for (i = 0; i < 7; i ++ ) { UCB2IFG &= ~UCRXIFG; UCB2TXBUF = 1; // load dummy byte 1 for clk - while (!(UCB2IFG & UCRXIFG)); - ReadData[i] = UCB2RXBUF; - } + while (!(UCB2IFG & UCRXIFG)); + ReadData[i] = UCB2RXBUF; + } LCD_CS_RST_OUT |= LCD_CS_PIN; // Stop Transfer CS = 1 - + LCD_SPI_SEL |= LCD_MOSI_PIN; //Change SPI2C Dir LCD_SPI_SEL &= ~LCD_MISO_PIN; LCD_CS_RST_DIR |= LCD_MOSI_PIN + LCD_CLK_PIN; LCD_CS_RST_DIR &= ~LCD_MISO_PIN; - - Value = (ReadData[5] << 8) + ReadData[6]; + + Value = (ReadData[5] << 8) + ReadData[6]; return Value; } /**********************************************************************//** - * @brief Draw a Pixel of grayscale at coordinate (x,y) to LCD - * - * @param x x-coordinate for grayscale value - * + * @brief Draw a Pixel of grayscale at coordinate (x,y) to LCD + * + * @param x x-coordinate for grayscale value + * * @param y y-coordinate for grayscale value - * - * @param GrayScale The intended grayscale value of the pixel - one of + * + * @param GrayScale The intended grayscale value of the pixel - one of * four possible settings. - * + * * @return none *************************************************************************/ void halLcdPixel( int x, int y, unsigned char GrayScale) { int Address, Value; unsigned char offset; - + //Each line increments by 0x20 if ( (x>=0 ) && (x=0) && (y> 3) ; //Narrow down to 8 possible pixels - + Address = (y << 5) + (x >> 3) ; //Narrow down to 8 possible pixels + Value = LCD_MEM[(y << 4)+ y + (x>>3)]; //y * 17 --> row. x>>3 --> column - + offset = (x & 0x07) << 1; //3 LSBs = pos. within the 8 columns Value &= ~ (3 << offset); //clear out the corresponding bits Value |= GrayScale << offset; //set pixel to GrayScale level - + halLcdDrawBlock( Address, Value ); } } /**********************************************************************//** * @brief Clears entire LCD CGRAM as well as LCD_MEM. - * + * * @param none - * + * * @return none *************************************************************************/ void halLcdClearScreen(void) { int i, j, k, Current_Location = 0; - halLcdSetAddress(0); - + halLcdSetAddress(0); + for (i=0; i < 110; i++) { //prepare to send image LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer for ( k = 0; k < 3; k++ ) { - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = Draw_Block_Value_Macro[k]; // Load data } while (UCB2STAT & UCBUSY); LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = Draw_Block_Value_Macro[3]; // Load data - + //send blank line for (j=0; j < 17; j++) { LCD_MEM[ LcdTableAddress++ ] = 0x00; - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = 0x00; // Load data - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = 0x00; // Load data - } - //Clear the partially visible block at the edge of the screen - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + } + //Clear the partially visible block at the edge of the screen + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = 0x00; // Load data - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = 0x00; // Load data while (UCB2STAT & UCBUSY); LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer - + Current_Location += 0x20; halLcdSetAddress(Current_Location ); } - + halLcdSetAddress(0); } /**********************************************************************//** - * @brief Loads an image of size = rows * columns, starting at the + * @brief Loads an image of size = rows * columns, starting at the * coordinate (x,y). - * + * * @param Image[] The image to be loaded - * + * * @param Rows The number of rows in the image. Size = Rows * Columns. - * + * * @param Columns The number of columns in the image. Size = Rows * Columns. - * - * @param x x-coordinate of the image's starting location - * - * @param y y-coordinate of the image's starting location - * + * + * @param x x-coordinate of the image's starting location + * + * @param y y-coordinate of the image's starting location + * * @return none *************************************************************************/ void halLcdImage(const unsigned int Image[], int Columns, int Rows, int x, int y) -{ +{ int i, CurrentLocation; - + CurrentLocation = (y << 5) + (x >> 3); halLcdSetAddress(CurrentLocation); for (i=0; i < Rows; i++) @@ -575,31 +575,31 @@ void halLcdImage(const unsigned int Image[], int Columns, int Rows, int x, int y } /**********************************************************************//** - * @brief Writes Value to LCD CGram and MSP430 internal LCD table. - * + * @brief Writes Value to LCD CGram and MSP430 internal LCD table. + * * Also updates the LcdAddress and LcdTableAddress to the correct values. - * - * @param *value Pointer to the line to be written to the LCD. - * + * + * @param *value Pointer to the line to be written to the LCD. + * * @return none *************************************************************************/ void halLcdDrawCurrentLine(const unsigned int *value, int Columns) -{ +{ unsigned char i; - + //prepare to send image LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer for ( i = 0; i < 3; i++ ) { - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = Draw_Block_Value_Macro[i]; // Load data } while (UCB2STAT & UCBUSY); LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = Draw_Block_Value_Macro[3]; // Load data - + //send the image for ( i = 0; i < Columns; i++ ) { @@ -608,27 +608,27 @@ void halLcdDrawCurrentLine(const unsigned int *value, int Columns) break; } LCD_MEM[ LcdTableAddress++ ] = *value; - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = (*value) >> 8; // Load data - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = (*value++) & 0xFF; // Load data } while (UCB2STAT & UCBUSY); - LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer + LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer } /**********************************************************************//** - * @brief Clears an image of size rows x columns starting at (x, y). - * + * @brief Clears an image of size rows x columns starting at (x, y). + * * @param Columns The size, in columns, of the image to be cleared. - * + * * @param Rows The size, in rows, of the image to be cleared. - * + * * @param x x-coordinate of the image to be cleared - * + * * @param y y-coordinate of the image to be cleared - * + * * @return none *************************************************************************/ void halLcdClearImage(int Columns, int Rows, int x, int y) @@ -636,111 +636,111 @@ void halLcdClearImage(int Columns, int Rows, int x, int y) int i,j,k, Current_Location; Current_Location = (y << 5) + (x >> 3); halLcdSetAddress( Current_Location ); - + for (i=0; i < Rows; i++) { //prepare to send image LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer for ( k = 0; k < 3; k++ ) { - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = Draw_Block_Value_Macro[k]; // Load data } while (UCB2STAT & UCBUSY); LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = Draw_Block_Value_Macro[3]; // Load data - + //send blank line for (j=0; j < Columns; j++) { LCD_MEM[ LcdTableAddress++ ] = 0x00; - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = 0x00; // Load data - while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG + while (!(UCB2IFG & UCTXIFG)); // Wait for TXIFG UCB2TXBUF = 0x00; // Load data - } + } while (UCB2STAT & UCBUSY); LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer - + Current_Location += 0x20; halLcdSetAddress(Current_Location ); } } /**********************************************************************//** - * @brief Writes Value to LCD CGRAM. Pointers internal to the LCD - * are also updated. - * + * @brief Writes Value to LCD CGRAM. Pointers internal to the LCD + * are also updated. + * * @param Value The value to be written to the current LCD pointer - * + * * @return none *************************************************************************/ void halLcdDrawTextBlock(unsigned int Value) -{ +{ int temp; - - Draw_Block_Value_Macro[4] = Value >> 8; - Draw_Block_Value_Macro[5] = Value & 0xFF; - LCD_MEM[ LcdTableAddress ] = Value; - + + Draw_Block_Value_Macro[4] = Value >> 8; + Draw_Block_Value_Macro[5] = Value & 0xFF; + LCD_MEM[ LcdTableAddress ] = Value; + halLcdSendCommand(Draw_Block_Value_Macro); - + LcdAddress++; temp = LcdAddress >> 5; // Divided by 0x20 - temp = temp + (temp << 4); + temp = temp + (temp << 4); //Multiplied by (1+16) and added by the offset - LcdTableAddress = temp + (LcdAddress & 0x1F); - - // If LcdAddress gets off the right edge, move to next line + LcdTableAddress = temp + (LcdAddress & 0x1F); + + // If LcdAddress gets off the right edge, move to next line if ((LcdAddress & 0x1F) > 0x10) halLcdSetAddress( (LcdAddress & 0xFFE0) + 0x20 ); - + if (LcdAddress >= LCD_Size) - halLcdSetAddress( 0 ); + halLcdSetAddress( 0 ); } /**********************************************************************//** * @brief Displays the string to the LCD starting at current location. - * - * Writes all the data to LCD_MEM first, then updates all corresponding + * + * Writes all the data to LCD_MEM first, then updates all corresponding * LCD CGRAM locations at once, in a continuous fashion. - * + * * @param String[] The string to be displayed on LCD. - * - * @param TextStyle Value that specifies whether the string is to be - * inverted or overwritten. - * - Invert = 0x01 - * - Overwrite = 0x04 - * + * + * @param TextStyle Value that specifies whether the string is to be + * inverted or overwritten. + * - Invert = 0x01 + * - Overwrite = 0x04 + * * @return none *************************************************************************/ -void halLcdPrint( char String[], unsigned char TextStyle) +void halLcdPrint( char String[], unsigned char TextStyle) { int i, j, Counter=0, BlockValue; int Address, LCD_MEM_Add, ActualAddress; int temp; char LookUpChar; - + ActualAddress = LcdAddress; - Counter = LcdAddress & 0x1F; + Counter = LcdAddress & 0x1F; i=0; - + while (String[i]!=0) // Stop on null character - { - LookUpChar = fonts_lookup[String[i]]; - - for (j=0;j < FONT_HEIGHT ;j++) + { + LookUpChar = fonts_lookup[String[i]]; + + for (j=0;j < FONT_HEIGHT ;j++) { Address = ActualAddress + j*0x20; temp = Address >> 5; temp += (temp <<4); - LCD_MEM_Add = temp + (Address & 0x1F); - + LCD_MEM_Add = temp + (Address & 0x1F); + BlockValue = LCD_MEM[ LCD_MEM_Add ]; - + if(TextStyle & GRAYSCALE_TEXT) { if (TextStyle & INVERT_TEXT) @@ -750,130 +750,130 @@ void halLcdPrint( char String[], unsigned char TextStyle) BlockValue |= 0xAAAA - GrayScale_fonts[LookUpChar*(FONT_HEIGHT+1) +j]; else if (TextStyle & OVERWRITE_TEXT) - BlockValue = GrayScale_fonts[LookUpChar*(FONT_HEIGHT+1) +j]; + BlockValue = GrayScale_fonts[LookUpChar*(FONT_HEIGHT+1) +j]; else BlockValue |= GrayScale_fonts[LookUpChar*(FONT_HEIGHT+1) +j]; } else - { - if (TextStyle & INVERT_TEXT) + { + if (TextStyle & INVERT_TEXT) if (TextStyle & OVERWRITE_TEXT) - BlockValue = 0xFFFF - fonts[LookUpChar*13+j]; + BlockValue = 0xFFFF - fonts[LookUpChar*13+j]; else - BlockValue |= 0xFFFF - fonts[LookUpChar*13+j]; - - else + BlockValue |= 0xFFFF - fonts[LookUpChar*13+j]; + + else if (TextStyle & OVERWRITE_TEXT) - BlockValue = fonts[LookUpChar*(FONT_HEIGHT+1) +j]; + BlockValue = fonts[LookUpChar*(FONT_HEIGHT+1) +j]; else - BlockValue |= fonts[LookUpChar*(FONT_HEIGHT+1) +j]; + BlockValue |= fonts[LookUpChar*(FONT_HEIGHT+1) +j]; } - halLcdDrawBlock( Address, BlockValue); + halLcdDrawBlock( Address, BlockValue); } - + Counter++; if (Counter == 17) { - Counter = 0; + Counter = 0; ActualAddress += 0x20*FONT_HEIGHT - 16; if (ActualAddress > LCD_Last_Pixel-0x20*FONT_HEIGHT ) ActualAddress = 0; } - else + else ActualAddress++; i++; } halLcdSetAddress(ActualAddress); - + } /**********************************************************************//** - * @brief Displays the string to the LCD starting at (x,y) location. - * - * Writes all the data to LCD_MEM first, then updates all corresponding + * @brief Displays the string to the LCD starting at (x,y) location. + * + * Writes all the data to LCD_MEM first, then updates all corresponding * LCD CGRAM locations at once, in a continuous fashion. - * + * * @param String[] String to be displayed on LCD - * - * @param x x-coordinate of the write location on the LCD - * + * + * @param x x-coordinate of the write location on the LCD + * * @param y y-coordinate of the write location on the LCD - * - * @param TextStyle Value that specifies whether the string is to be - * inverted or overwritten. - * - Invert = 0x01 - * - Overwrite = 0x04 + * + * @param TextStyle Value that specifies whether the string is to be + * inverted or overwritten. + * - Invert = 0x01 + * - Overwrite = 0x04 *************************************************************************/ -void halLcdPrintXY( char String[], int x, int y, unsigned char TextStyle) +void halLcdPrintXY( char String[], int x, int y, unsigned char TextStyle) { //Each line increments by 0x20 - halLcdSetAddress( (y << 5) + (x >> 3)) ; //Narrow down to 8 possible pixels + halLcdSetAddress( (y << 5) + (x >> 3)) ; //Narrow down to 8 possible pixels halLcdPrint(String, TextStyle); } /**********************************************************************//** - * @brief Displays a string on the LCD on the specified line. - * + * @brief Displays a string on the LCD on the specified line. + * * @param String[] The string to be displayed on LCD. - * + * * @param Line The line on the LCD on which to print the string. - * - * @param TextStyle Value that specifies whether the string is to be - * inverted or overwritten. - * - Invert = 0x01 - * - Overwrite = 0x04 - * + * + * @param TextStyle Value that specifies whether the string is to be + * inverted or overwritten. + * - Invert = 0x01 + * - Overwrite = 0x04 + * * @return none *************************************************************************/ -void halLcdPrintLine(char String[], unsigned char Line, unsigned char TextStyle) +void halLcdPrintLine(char String[], unsigned char Line, unsigned char TextStyle) { - int temp; + int temp; temp = Line * FONT_HEIGHT ; - halLcdSetAddress( temp << 5 ) ; // 0x20 = 2^5 + halLcdSetAddress( temp << 5 ) ; // 0x20 = 2^5 halLcdPrint(String, TextStyle); } /**********************************************************************//** - * @brief Prints a string beginning on a given line and column. - * + * @brief Prints a string beginning on a given line and column. + * * @param String[] The string to be displayed on LCD. - * + * * @param Line The line on which to print the string of text - * + * * @param Col The column on which to print the string of text - * - * @param TextStyle Value that specifies whether the string is to be - * inverted or overwritten. - * - Invert = 0x01 - * - Overwrite = 0x04 - * + * + * @param TextStyle Value that specifies whether the string is to be + * inverted or overwritten. + * - Invert = 0x01 + * - Overwrite = 0x04 + * * @return none *************************************************************************/ void halLcdPrintLineCol(char String[], unsigned char Line, unsigned char Col, - unsigned char TextStyle) + unsigned char TextStyle) { - int temp; - + int temp; + temp = Line * FONT_HEIGHT; temp <<= 5; temp += Col; - - halLcdSetAddress( temp ) ; // 0x20 = 2^5 + + halLcdSetAddress( temp ) ; // 0x20 = 2^5 halLcdPrint(String, TextStyle); } /**********************************************************************//** * @brief Draws a horizontral line from (x1,y) to (x2,y) of GrayScale level - * - * @param x1 x-coordinate of the first point - * + * + * @param x1 x-coordinate of the first point + * * @param x2 x-coordinate of the second point - * + * * @param y y-coordinate of both points - * + * * @param GrayScale Grayscale level of the horizontal line - * + * * @return none *************************************************************************/ void halLcdHLine( int x1, int x2, int y, unsigned char GrayScale) @@ -881,27 +881,27 @@ void halLcdHLine( int x1, int x2, int y, unsigned char GrayScale) int x_dir, x; if ( x1 < x2 ) x_dir = 1; - else + else x_dir = -1; - x = x1; + x = x1; while (x != x2) { - halLcdPixel( x,y, GrayScale); + halLcdPixel( x,y, GrayScale); x += x_dir; } } /**********************************************************************//** * @brief Draws a vertical line from (x,y1) to (x,y2) of GrayScale level - * + * * @param x x-coordinate of both points - * - * @param y1 y-coordinate of the first point - * + * + * @param y1 y-coordinate of the first point + * * @param y2 y-coordinate of the second point - * + * * @param GrayScale GrayScale level of the vertical line - * + * * @return none *************************************************************************/ void halLcdVLine( int x, int y1, int y2, unsigned char GrayScale) @@ -909,36 +909,36 @@ void halLcdVLine( int x, int y1, int y2, unsigned char GrayScale) int y_dir, y; if ( y1 < y2 ) y_dir = 1; - else + else y_dir = -1; - y = y1; + y = y1; while (y != y2) { - halLcdPixel( x,y, GrayScale); + halLcdPixel( x,y, GrayScale); y += y_dir; } } /**********************************************************************//** * @brief Draws a line from (x1,y1) to (x2,y2) of GrayScale level. - * + * * Uses Bresenham's line algorithm. - * - * @param x1 x-coordinate of the first point - * + * + * @param x1 x-coordinate of the first point + * * @param y1 y-coordinate of the first point - * + * * @param x2 x-coordinate of the second point - * + * * @param y2 y-coordinate of the second point - * - * @param GrayScale Grayscale level of the line - * + * + * @param GrayScale Grayscale level of the line + * * @return none *************************************************************************/ -void halLcdLine( int x1, int y1, int x2, int y2, unsigned char GrayScale) +void halLcdLine( int x1, int y1, int x2, int y2, unsigned char GrayScale) { - int x, y, deltay, deltax, d; + int x, y, deltay, deltax, d; int x_dir, y_dir; if ( x1 == x2 ) @@ -955,7 +955,7 @@ void halLcdLine( int x1, int y1, int x2, int y2, unsigned char GrayScale) if (y1 > y2) y_dir = -1; else y_dir = 1; - + x = x1; y = y1; deltay = ABS(y2 - y1); @@ -975,7 +975,7 @@ void halLcdLine( int x1, int y1, int x2, int y2, unsigned char GrayScale) y += y_dir; } x += x_dir; - } + } } else { @@ -991,30 +991,30 @@ void halLcdLine( int x1, int y1, int x2, int y2, unsigned char GrayScale) x += x_dir; } y += y_dir; - } + } } - } + } } } /**********************************************************************//** * @brief Draw a circle of Radius with center at (x,y) of GrayScale level. - * + * * Uses Bresenham's circle algorithm - * + * * @param x x-coordinate of the circle's center point - * + * * @param y y-coordinate of the circle's center point - * + * * @param Radius Radius of the circle - * - * @param GrayScale Grayscale level of the circle + * + * @param GrayScale Grayscale level of the circle *************************************************************************/ void halLcdCircle(int x, int y, int Radius, int GrayScale) { int xx, yy, ddF_x, ddF_y, f; - + ddF_x = 0; ddF_y = -(2 * Radius); f = 1 - Radius; @@ -1052,71 +1052,71 @@ void halLcdCircle(int x, int y, int Radius, int GrayScale) } /**********************************************************************//** - * @brief Scrolls a single row of pixels one column to the left. - * - * The column that is scrolled out of the left side of the LCD will be - * displayed the right side of the LCD. - * + * @brief Scrolls a single row of pixels one column to the left. + * + * The column that is scrolled out of the left side of the LCD will be + * displayed the right side of the LCD. + * * @param y The row of pixels to scroll. y = 0 is at the top-left - * corner of the LCD. - * + * corner of the LCD. + * * @return none *************************************************************************/ void halLcdScrollRow(int y) { int i, Address, LcdTableAddressTemp; unsigned int temp; - + Address = y << 5; - + halLcdSetAddress( Address ); - + //Multiplied by (1+16) and added by the offset - LcdTableAddressTemp = y + (y << 4); + LcdTableAddressTemp = y + (y << 4); temp = ((LCD_MEM[LcdTableAddressTemp] & 0x0003) <<14); - - for (i = 0; i < 0x10; i++) + + for (i = 0; i < 0x10; i++) halLcdDrawCurrentBlock( ( (LCD_MEM[LcdTableAddressTemp+i] & 0xFFFC ) >> 2 ) \ + ((LCD_MEM[LcdTableAddressTemp+i+1] & 0x0003) << 14 )); - - halLcdDrawCurrentBlock( (( LCD_MEM[LcdTableAddressTemp + 0x10] & 0xFFFC ) >> 2) + temp); + + halLcdDrawCurrentBlock( (( LCD_MEM[LcdTableAddressTemp + 0x10] & 0xFFFC ) >> 2) + temp); } /**********************************************************************//** - * @brief Scrolls multiple rows of pixels, yStart to yEnd, - * one column to the left. - * - * The column that is scrolled out of the left side of the LCD will be - * displayed the right side of the LCD. y = 0 is at the top-left of the + * @brief Scrolls multiple rows of pixels, yStart to yEnd, + * one column to the left. + * + * The column that is scrolled out of the left side of the LCD will be + * displayed the right side of the LCD. y = 0 is at the top-left of the * LCD screen. - * + * * @param yStart The beginning row to be scrolled - * - * @param yEnd The last row to be scrolled - * + * + * @param yEnd The last row to be scrolled + * * @return none *************************************************************************/ void halLcdHScroll(int yStart, int yEnd) { - int i ; - + int i ; + for (i = yStart; i < yEnd+1; i++) halLcdScrollRow(i); } /**********************************************************************//** - * @brief Scrolls a line of text one column to the left. - * - * @param Line The line of text to be scrolled. - * + * @brief Scrolls a line of text one column to the left. + * + * @param Line The line of text to be scrolled. + * * @return none *************************************************************************/ void halLcdScrollLine(int Line) { int i, Row ; - + Row = Line * FONT_HEIGHT; - + for (i = Row; i < Row + FONT_HEIGHT ; i++) halLcdScrollRow(i); } diff --git a/Demo/MSP430X_MSP430F5438_IAR/ParTest.c b/Demo/MSP430X_MSP430F5438_IAR/ParTest.c index 477ff9836..688deaa5c 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/ParTest.c +++ b/Demo/MSP430X_MSP430F5438_IAR/ParTest.c @@ -74,6 +74,7 @@ void vParTestInitialise( void ) void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue ) { + /* Only two LEDs are provided on the hardware. */ taskENTER_CRITICAL(); { if( xValue != pdFALSE ) @@ -85,6 +86,9 @@ void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue ) case 1: LED_PORT_OUT |= LED_2; break; + + default: /* Nothing to do here, there are only two LEDs. */ + break; } } else @@ -96,6 +100,8 @@ void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue ) case 1: LED_PORT_OUT &= ~LED_2; break; + default: /* Nothing to do here, there are only two LEDs. */ + break; } } } @@ -128,6 +134,8 @@ void vParTestToggleLED( unsigned portBASE_TYPE uxLED ) LED_PORT_OUT &= ~LED_2; } break; + default: /* Nothing to do here, there are only two LEDs. */ + break; } } taskEXIT_CRITICAL(); diff --git a/Demo/MSP430X_MSP430F5438_IAR/RTOSDemo.ewp b/Demo/MSP430X_MSP430F5438_IAR/RTOSDemo.ewp index c05a495b5..1262bc5cb 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/RTOSDemo.ewp +++ b/Demo/MSP430X_MSP430F5438_IAR/RTOSDemo.ewp @@ -1862,6 +1862,9 @@ $PROJ_DIR$\RegTest.s43 + + $PROJ_DIR$\RunTimeStatsConfig.c + $PROJ_DIR$\serial.c diff --git a/Demo/MSP430X_MSP430F5438_IAR/RegTest.s43 b/Demo/MSP430X_MSP430F5438_IAR/RegTest.s43 index a750e8269..98478adc6 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/RegTest.s43 +++ b/Demo/MSP430X_MSP430F5438_IAR/RegTest.s43 @@ -53,8 +53,16 @@ #include "msp430.h" #include "FreeRTOSConfig.h" +/* + * The definition of the "register test" tasks, as described at the top of + * main.c + */ + + + IMPORT usRegTest1Counter IMPORT usRegTest2Counter + IMPORT vPortYield EXPORT vRegTest1Task EXPORT vRegTest2Task @@ -63,6 +71,7 @@ vRegTest1Task: + /* Fill each general purpose register with a known value. */ movx.a #0x44444, r4 movx.a #0x55555, r5 movx.a #0x66666, r6 @@ -78,6 +87,9 @@ vRegTest1Task: prvRegTest1Loop: + /* Test each general purpose register to check that it still contains the + expected known value, jumping to vRegTest1Error if any register contains + an unexpected value. */ cmpx.a #0x44444, r4 jne vRegTest1Error cmpx.a #0x55555, r5 @@ -102,7 +114,12 @@ prvRegTest1Loop: jne vRegTest1Error cmpx.a #0xfffff, r15 jne vRegTest1Error + + /* This task is still running without jumping to vRegTest1Error, so increment + the loop counter so the check task knows the task is running error free. */ incx.w &usRegTest1Counter + + /* Loop again, performing the same tests. */ jmp prvRegTest1Loop nop @@ -110,49 +127,56 @@ prvRegTest1Loop: vRegTest1Error: jmp vRegTest1Error nop + /*-----------------------------------------------------------*/ +/* See the comments in vRegTest1Task. This task is the same, it just uses +different values in its registers. */ vRegTest2Task: - movx.a #0x44444, r4 - movx.a #0x55555, r5 - movx.a #0x66666, r6 - movx.a #0x77777, r7 - movx.a #0x88888, r8 - movx.a #0x99999, r9 - movx.a #0xaaaaa, r10 - movx.a #0xbbbbb, r11 - movx.a #0xccccc, r12 - movx.a #0xddddd, r13 - movx.a #0xeeeee, r14 - movx.a #0xfffff, r15 + movx.a #0x14441, r4 + movx.a #0x15551, r5 + movx.a #0x16661, r6 + movx.a #0x17771, r7 + movx.a #0x18881, r8 + movx.a #0x19991, r9 + movx.a #0x1aaa1, r10 + movx.a #0x1bbb1, r11 + movx.a #0x1ccc1, r12 + movx.a #0x1ddd1, r13 + movx.a #0x1eee1, r14 + movx.a #0x1fff1, r15 prvRegTest2Loop: - cmpx.a #0x44444, r4 + cmpx.a #0x14441, r4 jne vRegTest2Error - cmpx.a #0x55555, r5 + cmpx.a #0x15551, r5 jne vRegTest2Error - cmpx.a #0x66666, r6 + cmpx.a #0x16661, r6 jne vRegTest2Error - cmpx.a #0x77777, r7 + cmpx.a #0x17771, r7 jne vRegTest2Error - cmpx.a #0x88888, r8 + cmpx.a #0x18881, r8 jne vRegTest2Error - cmpx.a #0x99999, r9 + cmpx.a #0x19991, r9 jne vRegTest2Error - cmpx.a #0xaaaaa, r10 + cmpx.a #0x1aaa1, r10 jne vRegTest2Error - cmpx.a #0xbbbbb, r11 + cmpx.a #0x1bbb1, r11 jne vRegTest2Error - cmpx.a #0xccccc, r12 + cmpx.a #0x1ccc1, r12 jne vRegTest2Error - cmpx.a #0xddddd, r13 + cmpx.a #0x1ddd1, r13 jne vRegTest2Error - cmpx.a #0xeeeee, r14 + cmpx.a #0x1eee1, r14 jne vRegTest2Error - cmpx.a #0xfffff, r15 + cmpx.a #0x1fff1, r15 jne vRegTest2Error + + /* Also perform a manual yield, just to increase the scope of the test. */ + calla #vPortYield + incx.w &usRegTest2Counter jmp prvRegTest2Loop nop diff --git a/Demo/MSP430X_MSP430F5438_IAR/RunTimeStatsConfig.c b/Demo/MSP430X_MSP430F5438_IAR/RunTimeStatsConfig.c new file mode 100644 index 000000000..94dd0f953 --- /dev/null +++ b/Demo/MSP430X_MSP430F5438_IAR/RunTimeStatsConfig.c @@ -0,0 +1,115 @@ +/* + FreeRTOS V6.1.0 - 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 books - available as PDF or paperback * + * * + * "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. +*/ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" + +/* Hardware includes. */ +#include "msp430.h" +#include "hal_MSP-EXP430F5438.h" + +/* This demo uses Timer A1 to generate the time base for gathering run time +statistics information. Run time statistics show much processing time has +been allocated to each task since the application booted. */ + +/* The time base for the run time stats is generated by a 16 bit timer. Each +time the timer overflows ulStatsOverflowCount is incremented. Therefore, +when converting the total run time to a 32 bit number, the most significant two +bytes are given by ulStatsOverflowCount and the least significant two bytes are +given by the current timer counter value. Care must be taken with data +consistency when combining the two in case a timer overflow occurs as the +value is being read. */ +volatile unsigned long ulStatsOverflowCount = 0; + +/*-----------------------------------------------------------*/ + +void vConfigureTimerForRunTimeStats( void ) +{ + /* Ensure the timer is stopped. */ + TA1CTL = 0; + + /* Run the timer from the ACLK/4. */ + TA1CTL = TASSEL_1 | ID__4; + + /* Clear everything to start with. */ + TA1CTL |= TACLR; + + /* Enable the interrupts. */ + TA1CCTL0 = CCIE; + + /* Start up clean. */ + TA1CTL |= TACLR; + + /* Continuous mode. */ + TA1CTL |= MC__CONTINOUS; +} +/*-----------------------------------------------------------*/ + +#pragma vector=TIMER1_A0_VECTOR +static __interrupt void prvRunTimeStatsOverflowISR( void ) +{ + ulStatsOverflowCount++; +} +/*-----------------------------------------------------------*/ + +inline unsigned long ulGetRunTimeStatsTime( void ) +{ +unsigned long ulReturn; + + TA1CTL &= ~MC__CONTINOUS; + ulReturn = ( ( ulStatsOverflowCount << 16UL ) | ( unsigned long ) TA1R ); + TA1CTL |= MC__CONTINOUS; + + return ulReturn; +} +/*-----------------------------------------------------------*/ diff --git a/Demo/MSP430X_MSP430F5438_IAR/lnk430F5438A_mod.xcl b/Demo/MSP430X_MSP430F5438_IAR/lnk430F5438A_mod.xcl index 99dc499d9..332a19594 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/lnk430F5438A_mod.xcl +++ b/Demo/MSP430X_MSP430F5438_IAR/lnk430F5438A_mod.xcl @@ -195,9 +195,9 @@ // *** Modified to place code in high memory and insodoing, testing the port. // Original code -//-P(CODE)CODE=5C00-FF7F,10000-45BFF +-P(CODE)CODE=5C00-FF7F,10000-45BFF // Modified code --P(CODE)CODE=10000-45BFF +//-P(CODE)CODE=10000-45BFF -Z(CODE)CODE_ID diff --git a/Demo/MSP430X_MSP430F5438_IAR/main.c b/Demo/MSP430X_MSP430F5438_IAR/main.c index 9a922b81c..fe5e57fd2 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/main.c +++ b/Demo/MSP430X_MSP430F5438_IAR/main.c @@ -51,6 +51,87 @@ licensing and training services. */ +/* + * The documentation page for this demo available on http://www.FreeRTOS.org + * documents the hardware configuration required to run this demo. It also + * provides more information on the expected demo application behaviour. + * + * main() creates all the demo application tasks, then starts the scheduler. + * A lot of the created tasks are from the pool of "standard demo" tasks. The + * web documentation provides more details of the standard demo tasks, which + * provide no particular functionality but do provide good examples of how to + * use the FreeRTOS API. + * + * In addition to the standard demo tasks, the following tasks, interrupts and + * tests are defined and/or created within this file: + * + * "LCD" task - The LCD task is a 'gatekeeper' task. It is the only task that + * is permitted to access the LCD and therefore ensures access to the LCD is + * always serialised and there are no mutual exclusion issues. When a task or + * an interrupt wants to write to the LCD, it does not access the LCD directly + * but instead sends the message to the LCD task. The LCD task then performs + * the actual LCD output. This mechanism also allows interrupts to, in effect, + * write to the LCD by sending messages to the LCD task. + * + * The LCD task is also a demonstration of a 'controller' task design pattern. + * Some tasks do not actually send a string to the LCD task directly, but + * instead send a command that is interpreted by the LCD task. In a normal + * application these commands can be control values or set points, in this + * simple example the commands just result in messages being displayed on the + * LCD. + * + * "Button Poll" task - This task polls the state of the 'up' key on the + * joystick input device. It uses the vTaskDelay() API function to control + * the poll rate to ensure debouncing is not necessary and that the task does + * not use all the available CPU processing time. + * + * Button Interrupt and run time stats display - The select button on the + * joystick input device is configured to generate an external interrupt. The + * handler for this interrupt sends a message to LCD task, which interprets the + * message to mean, firstly write a message to the LCD, and secondly, generate + * a table of run time statistics. The run time statistics are displayed as a + * table that contains information on how much processing time each task has + * been allocated since the application started to execute. This information + * is provided both as an absolute time, and as a percentage of the total run + * time. The information is displayed in the terminal IO window of the IAR + * embedded workbench. The online documentation for this demo shows a screen + * shot demonstrating where the run time stats can be viewed. + * + * Idle Hook - The idle hook is a function that is called on each iteration of + * the idle task. In this case it is used to place the processor into a low + * power mode. Note however that this application is implemented using standard + * components, and is therefore not optimised for low power operation. Lower + * power consumption would be achieved by converting polling tasks into event + * driven tasks, and slowing the tick interrupt frequency. + * + * "Check" function called from the tick hook - The tick hook is called during + * each tick interrupt. It is called from an interrupt context so must execute + * quickly, not attempt to block, and not call any FreeRTOS API functions that + * do not end in "FromISR". In this case the tick hook executes a 'check' + * function. This only executes every five seconds. Its main function is to + * check that all the standard demo tasks are still operational. Each time it + * executes it sends a status code to the LCD task. The LCD task interprets the + * code and displays an appropriate message - which will be PASS if no tasks + * have reported any errors, or a message stating which task has reported an + * error. + * + * "Reg test" tasks - These fill the registers with known values, then check + * that each register still contains its expected value. Each task uses + * different values. The tasks run with very low priority so get preempted + * very frequently. A check variable is incremented on each iteration of the + * test loop. A register containing an unexpected value is indicative of an + * error in the context switching mechanism and will result in a branch to a + * null loop - which in turn will prevent the check variable from incrementing + * any further and allow the check task (described a above) to determine that an + * error has occurred. The nature of the reg test tasks necessitates that they + * are written in assembly code. + * + * *NOTE 2* vApplicationSetupTimerInterrupt() is called by the kernel to let + * the application set up a timer to generate the tick interrupt. In this + * example a timer A0 is used for this purpose. + * +*/ + /* Standard includes. */ #include @@ -88,30 +169,58 @@ of the same message and indicate what the status actually is. */ to send messages from tasks and interrupts the the LCD task. */ #define mainQUEUE_LENGTH ( 5 ) +/* Priorities used by the test and demo tasks. */ #define mainLCD_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainGENERIC_QUEUE_TEST_PRIORITY ( tskIDLE_PRIORITY ) /* The LED used by the comtest tasks. See the comtest.c file for more -information. In this case it is deliberately out of range as there are only -two LEDs, and they are both already in use. */ -#define mainCOM_TEST_LED ( 3 ) +information. */ +#define mainCOM_TEST_LED ( 1 ) /* The baud rate used by the comtest tasks described at the top of this file. */ -#define mainCOM_TEST_BAUD_RATE ( 9600 ) +#define mainCOM_TEST_BAUD_RATE ( 115200 ) + +/* The maximum number of lines of text that can be displayed on the LCD. */ +#define mainMAX_LCD_LINES ( 8 ) /*-----------------------------------------------------------*/ +/* + * The reg test tasks as described at the top of this file. + */ extern void vRegTest1Task( void *pvParameters ); extern void vRegTest2Task( void *pvParameters ); + +/* + * Configures clocks, LCD, port pints, etc. necessary to execute this demo. + */ static void prvSetupHardware( void ); -static void prvTerminalIOTask( void *pvParameters ); + +/* + * Definition of the LCD/controller task described in the comments at the top + * of this file. + */ +static void prvLCDTask( void *pvParameters ); + +/* + * Definition of the button poll task described in the comments at the top of + * this file. + */ static void prvButtonPollTask( void *pvParameters ); + +/* + * Converts a status message value into an appropriate string for display on + * the LCD. The string is written to pcBuffer. + */ static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue ); /*-----------------------------------------------------------*/ +/* Variables that are incremented on each iteration of the reg test tasks - +provided the tasks have not reported any errors. The check task inspects these +variables to ensure they are still incrementing as expected. If a variable +stops incrementing then it is likely that its associate task has stalled. */ volatile unsigned short usRegTest1Counter = 0, usRegTest2Counter = 0; -volatile unsigned long ulStatsOverflowCount = 0; /* The handle of the queue used to send messages from tasks and interrupts to the LCD task. */ @@ -121,19 +230,24 @@ static xQueueHandle xLCDQueue = NULL; task. */ typedef struct { - char cMessageID; /* << States what the message is. */ - unsigned long ulMessageValue; /* << States the message value (can be an integer, string pointer, etc. depending on the value of cMessageID. */ + char cMessageID; /* << States what the message is. */ + unsigned long ulMessageValue; /* << States the message value (can be an integer, string pointer, etc. depending on the value of cMessageID). */ } xQueueMessage; + /*-----------------------------------------------------------*/ void main( void ) { + /* Configure the peripherals used by this demo application. This includes + configuring the joystick input select button to generate interrupts. */ prvSetupHardware(); /* Create the queue used by tasks and interrupts to send strings to the LCD task. */ xLCDQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( xQueueMessage ) ); + /* If the queue could not be created then don't create any tasks that might + attempt to use the queue. */ if( xLCDQueue != NULL ) { /* Add the created queue to the queue registry so it can be viewed in @@ -145,22 +259,26 @@ void main( void ) vStartDynamicPriorityTasks(); vStartGenericQueueTasks( mainGENERIC_QUEUE_TEST_PRIORITY ); - /* Create the terminal IO and button poll tasks, as described at the top - of this file. */ - xTaskCreate( prvTerminalIOTask, ( signed char * ) "IO", configMINIMAL_STACK_SIZE * 2, NULL, mainLCD_TASK_PRIORITY, NULL ); + /* Create the LCD, button poll and register test tasks, as described at + the top of this file. */ + xTaskCreate( prvLCDTask, ( signed char * ) "LCD", configMINIMAL_STACK_SIZE * 2, NULL, mainLCD_TASK_PRIORITY, NULL ); xTaskCreate( prvButtonPollTask, ( signed char * ) "BPoll", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - - /* Create the register test tasks as described at the top of this file. */ xTaskCreate( vRegTest1Task, "Reg1", configMINIMAL_STACK_SIZE, NULL, 0, NULL ); xTaskCreate( vRegTest2Task, "Reg2", configMINIMAL_STACK_SIZE, NULL, 0, NULL ); + + /* Start the scheduler. */ vTaskStartScheduler(); } + /* If all is well then this line will never be reached. If it is reached + then it is likely that there was insufficient (FreeRTOS) heap memory space + to create the idle task. This may have been trapped by the malloc() failed + hook function, if one is configured. */ for( ;; ); } /*-----------------------------------------------------------*/ -static void prvTerminalIOTask( void *pvParameters ) +static void prvLCDTask( void *pvParameters ) { xQueueMessage xReceivedMessage; @@ -192,7 +310,7 @@ unsigned char ucLine = 1; xQueueReceive( xLCDQueue, &xReceivedMessage, portMAX_DELAY ); /* Clear the LCD if no room remains for any more text output. */ - if( ucLine > 8 ) + if( ucLine > mainMAX_LCD_LINES ) { halLcdClearScreen(); ucLine = 0; @@ -225,7 +343,7 @@ unsigned char ucLine = 1; the LCD - in this case the pointer to the string to print is sent directly in the - lMessageValue member of the + ulMessageValue member of the message. This just demonstrates a different communication technique. */ @@ -244,6 +362,9 @@ unsigned char ucLine = 1; break; } + /* Output the message that was placed into the cBuffer array within the + switch statement above, then move onto the next line ready for the next + message to arrive on the queue. */ halLcdPrintLine( cBuffer, ucLine, OVERWRITE_TEXT ); ucLine++; } @@ -260,7 +381,7 @@ static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue ) break; case mainERROR_DYNAMIC_TASKS : sprintf( pcBuffer, "Err: Dynamic tsks" ); break; - case mainERROR_COM_TEST : sprintf( pcBuffer, "Err: COM test" ); /* Error in COM test - is the Loopback connector connected? */ + case mainERROR_COM_TEST : sprintf( pcBuffer, "Err: COM test" ); break; case mainERROR_GEN_QUEUE_TEST : sprintf( pcBuffer, "Error: Gen Q test" ); break; @@ -286,6 +407,7 @@ xQueueMessage xMessage; if( ucState != 0 ) { + /* The button was pressed. */ ucState = pdTRUE; } @@ -307,6 +429,8 @@ xQueueMessage xMessage; static void prvSetupHardware( void ) { +/* Convert a Hz value to a KHz value, as required by the Init_FLL_Settle() +function. */ unsigned long ulCPU_Clock_KHz = ( configCPU_CLOCK_HZ / 1000UL ); halBoardInit(); @@ -316,64 +440,18 @@ unsigned long ulCPU_Clock_KHz = ( configCPU_CLOCK_HZ / 1000UL ); halButtonsInit( BUTTON_ALL ); halButtonsInterruptEnable( BUTTON_SELECT ); + + /* Initialise the LCD, but note that the backlight is not used as the + library function uses timer A0 to modulate the backlight, and this file + defines vApplicationSetupTimerInterrupt() to also use timer A0 to generate + the tick interrupt. If the backlight is required, then change either the + halLCD library or vApplicationSetupTimerInterrupt() to use a different + timer. Timer A1 is used for the run time stats time base6. */ halLcdInit(); - halLcdBackLightInit(); - halLcdSetBackLight( 0 ); halLcdSetContrast( 100 ); halLcdClearScreen(); halLcdPrintLine( " www.FreeRTOS.org", 0, OVERWRITE_TEXT ); - -while( ( halButtonsPressed() & BUTTON_UP ) == 0 ); -} -/*-----------------------------------------------------------*/ - -void vApplicationSetupTimerInterrupt( void ) -{ -const unsigned short usACLK_Frequency_Hz = 32768; - - /* Ensure the timer is stopped. */ - TA0CTL = 0; - - /* Run the timer from the ACLK. */ - TA0CTL = TASSEL_1; - - /* Clear everything to start with. */ - TA0CTL |= TACLR; - - /* Set the compare match value according to the tick rate we want. */ - TA0CCR0 = usACLK_Frequency_Hz / configTICK_RATE_HZ; - - /* Enable the interrupts. */ - TA0CCTL0 = CCIE; - - /* Start up clean. */ - TA0CTL |= TACLR; - - /* Up mode. */ - TA0CTL |= MC_1; -} -/*-----------------------------------------------------------*/ - -void vApplicationMallocFailedHook( void ) -{ - for( ;; ); -} -/*-----------------------------------------------------------*/ - -void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName ) -{ - ( void ) pxTask; - ( void ) pcTaskName; - - for( ;; ); -} -/*-----------------------------------------------------------*/ - -void vApplicationIdleHook( void ) -{ - /* Want to leave the SMCLK running so the COMTest tasks don't fail. */ - __bis_SR_register( LPM1_bits + GIE ); } /*-----------------------------------------------------------*/ @@ -413,8 +491,8 @@ static xQueueMessage xStatusMessage = { mainMESSAGE_STATUS, pdPASS }; xStatusMessage.ulMessageValue = mainERROR_GEN_QUEUE_TEST; } - /* Check the reg test tasks are still cycling. They will stop incrementing - their loop counters if they encounter an error. */ + /* Check the reg test tasks are still cycling. They will stop + incrementing their loop counters if they encounter an error. */ if( usRegTest1Counter == usLastRegTest1Counter ) { xStatusMessage.ulMessageValue = mainERROR_REG_TEST; @@ -435,17 +513,18 @@ static xQueueMessage xStatusMessage = { mainMESSAGE_STATUS, pdPASS }; ulCounter = 0; } + /* Just periodically toggle an LED to show that the tick interrupt is + running. Note that this access LED_PORT_OUT in a non-atomic way, so tasks + that access the same port must do so from a critical section. */ if( ( ulCounter & 0xff ) == 0 ) { if( ( LED_PORT_OUT & LED_1 ) == 0 ) { LED_PORT_OUT |= LED_1; - LED_PORT_OUT &= ~LED_2; } else { LED_PORT_OUT &= ~LED_1; - LED_PORT_OUT |= LED_2; } } } @@ -473,46 +552,68 @@ portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; } /*-----------------------------------------------------------*/ -void vConfigureTimerForRunTimeStats( void ) +/* The MSP430X port uses this callback function to configure its tick interrupt. +This allows the application to choose the tick interrupt source. +configTICK_INTERRUPT_VECTOR must also be set in FreeRTOSConfig.h to the correct +interrupt vector for the chosen tick interrupt source. This implementation of +vApplicationSetupTimerInterrupt() generates the tick from timer A0, so in this +case configTICK_INTERRUPT_VECTOR is set to TIMER0_A0_VECTOR. */ +void vApplicationSetupTimerInterrupt( void ) { +const unsigned short usACLK_Frequency_Hz = 32768; + /* Ensure the timer is stopped. */ - TA1CTL = 0; + TA0CTL = 0; - /* Run the timer from the ACLK/4. */ - TA1CTL = TASSEL_1 | ID__4; + /* Run the timer from the ACLK. */ + TA0CTL = TASSEL_1; /* Clear everything to start with. */ - TA1CTL |= TACLR; + TA0CTL |= TACLR; + + /* Set the compare match value according to the tick rate we want. */ + TA0CCR0 = usACLK_Frequency_Hz / configTICK_RATE_HZ; /* Enable the interrupts. */ - TA1CCTL0 = CCIE; + TA0CCTL0 = CCIE; /* Start up clean. */ - TA1CTL |= TACLR; + TA0CTL |= TACLR; - /* Continuous mode. */ - TA1CTL |= MC__CONTINOUS; + /* Up mode. */ + TA0CTL |= MC_1; } /*-----------------------------------------------------------*/ -#pragma vector=TIMER1_A0_VECTOR -static __interrupt void prvRunTimeStatsOverflowISR( void ) +void vApplicationIdleHook( void ) { - ulStatsOverflowCount++; + /* Called on each iteration of the idle task. In this case the idle task + just enters a low(ish) power mode. */ + __bis_SR_register( LPM1_bits + GIE ); } /*-----------------------------------------------------------*/ -inline unsigned long ulGetRunTimeStatsTime( void ) +void vApplicationMallocFailedHook( void ) { -unsigned long ulReturn; + /* Called if a call to pvPortMalloc() fails because there is insufficient + free memory available in the FreeRTOS heap. pvPortMalloc() is called + internally by FreeRTOS API functions that create tasks, queues or + semaphores. */ + taskDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ - TA1CTL &= ~MC__CONTINOUS; - ulReturn = ( ( ulStatsOverflowCount << 16UL ) | ( unsigned long ) TA1R ); - TA1CTL |= MC__CONTINOUS; +void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName ) +{ + ( void ) pxTask; + ( void ) pcTaskName; - return ulReturn; + /* Run time stack overflow checking is performed if + configconfigCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook + function is called if a stack overflow is detected. */ + taskDISABLE_INTERRUPTS(); + for( ;; ); } - - - +/*-----------------------------------------------------------*/ diff --git a/Demo/MSP430X_MSP430F5438_IAR/serial.c b/Demo/MSP430X_MSP430F5438_IAR/serial.c index 3e861f2f2..89ca091bd 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/serial.c +++ b/Demo/MSP430X_MSP430F5438_IAR/serial.c @@ -54,9 +54,11 @@ /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER. * - * This file only supports UART A0 in loopback mode, and has not been tested - * for real UART operation (only loopback mode) so is not guaranteed to have - * a correct baud rate configuration. + * This is not a proper UART driver. It only supports one port, uses loopback + * mode, and is used to test interrupts that use the FreeRTOS API as part of + * a wider test suite. Nor is it intended to show an efficient implementation + * of a UART interrupt service routine as queues are used to pass individual + * characters one at a time! */ /* Standard includes. */ @@ -70,9 +72,6 @@ /* Demo application includes. */ #include "serial.h" -/* Constants required to setup the hardware. */ -#define serTX_AND_RX ( ( unsigned portCHAR ) 0x03 ) - /* Misc. constants. */ #define serNO_BLOCK ( ( portTickType ) 0 ) @@ -123,9 +122,8 @@ unsigned portLONG ulBaudRateCount; } portEXIT_CRITICAL(); - /* Unlike other ports, this serial code does not allow for more than one - com port. We therefore don't return a pointer to a port structure and can - instead just return NULL. */ + /* Note the comments at the top of this file about this not being a generic + UART driver. */ return NULL; } /*-----------------------------------------------------------*/ @@ -149,6 +147,9 @@ signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed portCHAR cOut { signed portBASE_TYPE xReturn; + /* Send the next character to the queue of characters waiting transmission, + then enable the UART Tx interrupt, just in case UART transmission has already + completed and switched itself off. */ xReturn = xQueueSend( xCharsForTx, &cOutChar, xBlockTime ); UCA1IE |= UCTXIE; @@ -190,6 +191,14 @@ portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; } __bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF ); + + /* If writing to a queue caused a task to unblock, and the unblocked task + has a priority equal to or above the task that this interrupt interrupted, + then lHigherPriorityTaskWoken will have been set to pdTRUE internally within + xQueuesendFromISR(), and portEND_SWITCHING_ISR() will ensure that this + interrupt returns directly to the higher priority unblocked task. + + THIS MUST BE THE LAST THING DONE IN THE ISR. */ portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } diff --git a/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.dbgdt b/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.dbgdt index f81cb106b..ebf6bdf20 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.dbgdt +++ b/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.dbgdt @@ -26,12 +26,12 @@ 200111 - 20030010{W}Watch-0:TA1CTL4{W}Watch-0:ulSP_PC_Combined4300134139124100300Debug-Log300200100100100100100100150110$PROJ_DIR$\TermIOInput.txt1030015015030030000 + 20030010{W}Watch-0:TA1CTL4{W}Watch-0:ulSP_PC_Combined4300134139124100300Debug-Log300200100100100100100100150110$PROJ_DIR$\TermIOInput.txt10300150150300300001001 - + TabID-11539-27703 @@ -39,24 +39,24 @@ Workspace - RTOSDemo + RTOSDemoRTOSDemo/FreeRTOS_SourceRTOSDemo/FreeRTOS_Source/Portable - 0TabID-12395-27916Terminal I/OTerminalIO0TabID-25408-8444TasksTASKVIEW0 + 0TabID-12395-27916Terminal I/OTerminalIO0TabID-28694-31512Debug LogDebug-Log0 - TextEditor$WS_DIR$\MSP-EXP430F5438_HAL\hal_lcd.c08092798127996TextEditor$WS_DIR$\main.c03531383413834TextEditor$WS_DIR$\..\..\Source\queue.c04511934519345TextEditor$WS_DIR$\FreeRTOSConfig.h05439213921TextEditor$WS_DIR$\lnk430F5438A_mod.xcl017750815081TextEditor$WS_DIR$\..\..\Source\tasks.c015905021850218TextEditor$WS_DIR$\..\..\Source\portable\IAR\MSP430X\port.c01637271727160100000010000001 + TextEditor$WS_DIR$\main.c0237126301263000100000010000001 - iaridepm.enu1430fet1debuggergui.enu1-2-2532321-2-212115072024152749192262543788-2-2532399-2-212115072024152749238690543788-2-23821682-2-216843841002381391039119048203666 + iaridepm.enu1430fet1debuggergui.enu1-2-2716321-2-212115072024152749192262731161-2-2716399-2-212115072024152749238690731161-2-21981682-2-216842001002381203666119048203666 diff --git a/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.dni b/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.dni index a2dda48c2..10b76323c 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.dni +++ b/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.dni @@ -1,5 +1,5 @@ [DebugChecksum] -Checksum=-802929519 +Checksum=283457804 [DisAssemblyWindow] NumStates=_ 1 State 1=_ 1 @@ -14,7 +14,7 @@ Control Register=0 NextState0=0 NextState1=0 [Action Register] -Break=1 +Break=6 State Storage=0 [Profiling] Enabled=0 @@ -28,6 +28,10 @@ UseTrigger=1 TriggerName=main LimitSize=0 ByteLimit=50 +[Log file] +LoggingEnabled=_ 0 +LogFile=_ "" +Category=_ 0 [TermIOLog] LoggingEnabled=_ 0 LogFile=_ "" @@ -35,13 +39,9 @@ LogFile=_ "" Enabled=0 [DriverProfiling] Enabled=0 -Mode=303237632 +Mode=123810376 Graph=0 Symbiont=0 -[Log file] -LoggingEnabled=_ 0 -LogFile=_ "" -Category=_ 0 [Breakpoints] Count=0 [FET] diff --git a/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.wsdt b/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.wsdt index 1d55954a9..35acd8698 100644 --- a/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.wsdt +++ b/Demo/MSP430X_MSP430F5438_IAR/settings/RTOSDemo.wsdt @@ -3,7 +3,7 @@ - RTOSDemo/Release + RTOSDemo/Debug @@ -33,7 +33,7 @@ Workspace - RTOSDemoRTOSDemo/F5XX_6XX_Core_LibRTOSDemo/MSP-EXP430F5438_HALRTOSDemo/OutputRTOSDemo/UserExperienceDemo + RTOSDemoRTOSDemo/UserExperienceDemo @@ -53,14 +53,14 @@ - TextEditor$WS_DIR$\MSP-EXP430F5438_HAL\hal_lcd.c08092798127996TextEditor$WS_DIR$\main.c03531383413834TextEditor$WS_DIR$\..\..\Source\queue.c04511934519345TextEditor$WS_DIR$\FreeRTOSConfig.h05439213921TextEditor$WS_DIR$\lnk430F5438A_mod.xcl017750815081TextEditor$WS_DIR$\..\..\Source\tasks.c015905021850218TextEditor$WS_DIR$\..\..\Source\portable\IAR\MSP430X\port.c016372717271TextEditor$WS_DIR$\MSP-EXP430F5438_HAL\hal_MSP-EXP430F5438.h00669669TextEditor$WS_DIR$\MSP-EXP430F5438_HAL\hal_board.c04417251725TextEditor$WS_DIR$\serial.c0834515451590100000010000001 + TextEditor$WS_DIR$\main.c042117771177700100000010000001 - iaridepm.enu1-2-2645475-2-2331267197024271894283929658859-2-22931682-2-216842951002381300407197024271894 + iaridepm.enu1-2-2645475-2-2331267197024271894283929658859-2-22931682-2-216842951002381300407197024271894 -- 2.39.5