Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

Stuck after removing unused global variable

Posted by Fikus on October 22, 2008
Hi,
I modify the USB CDC example from Atmel for AVR32 (software pack):
FreeRTOS + USB CDC and I add files for serial communication (also from software pack) and keyboard scan example.
Everything worked just great. The ISR for keyboard is like:
(only one change compare to original file = sendqueue;
from global overview: I am trying to change using keypress value as global variable => to store each pressed key like item of queue => the same structure is used in FreeRTOS serial example from SW FRWK to store rx/tx chars)

/*
* EXT_INT_EXAMPLE_LINE3 interrupt service routine.
*/
#if __GNUC__
__attribute__((__naked__))
#elif __ICCAVR32__
#pragma shadow_registers = full // Naked.
#endif

static void vEIC_int_handler3_ISR( void )
{
/* This ISR can cause a context switch, so the first statement must be a
call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any
variable declarations. */
portENTER_SWITCHING_ISR();

prvEIC_ISR_NonNakedBehaviour( EXT_INT_EXAMPLE_LINE3, 3 );

/* Exit the ISR. If a task was woken by either a character being received
or transmitted then a context switch will occur. */
portEXIT_SWITCHING_ISR();
}


#if __GNUC__
__attribute__((__noinline__))
#elif __ICCAVR32__
#pragma optimize = no_inline
#endif

static portBASE_TYPE prvEIC_ISR_NonNakedBehaviour ( const unsigned int line_num, const unsigned int row_num)
{
/* Now we can declare the local variables. */
//portBASE_TYPE key_number;
portBASE_TYPE xTaskWokenByKey = pdFALSE;
portBASE_TYPE retstatus;
portBASE_TYPEline_number;
gpio_tgl_gpio_pin(AVR32_PIN_PA18);

line_number = eic_get_interrupt_pad_scan(&AVR32_EIC);
switch (line_number)
{
case SCAN_COL1_IDX :
key_number = 1;
break;
case SCAN_COL2_IDX :
key_number = 2;
break;
case SCAN_COL3_IDX :
key_number = 3;
break;
case SCAN_COL4_IDX :
key_number = 4;
break;
case SCAN_COL5_IDX :
key_number = 5;
break;
case SCAN_COL6_IDX :
key_number = 6;
break;
case SCAN_COL7_IDX :
key_number = 7;
break;
}
key_number=key_number+row_num*10;
eic_clear_interrupt_line(&AVR32_EIC, line_num);
/* Because FreeRTOS is not supposed to run with nested interrupts, put all OS
calls in a critical section . */
portENTER_CRITICAL();
retstatus = xQueueSendFromISR(xKeyPressed, &key_number, pdFALSE);
portEXIT_CRITICAL();

if( retstatus )
{
xTaskWokenByKey = pdTRUE;
}
/* The return value will be used by portEXIT_SWITCHING_ISR() to know if it
should perform a vTaskSwitchContext(). */
return xTaskWokenByKey;
}

Variable key_number is global, definition is in the beginning of file and it force to have some value (0). But if I change it to local, queuesendfromisr will not save value properly(nothing is stored to queue, however everything other is running ok) and after calling receive mcu stuck. If I not call Receive interrupt mcu execute without any problem. (But I can still use queuesend from different function and receive just work, but it doesnt get any characters from ISR)

Second weird thing is that I am forced to create this global value and put some value in it in the beginning and also use it once in code wherevery I can! Thats it = no useful using in code, it just must be created, otherwise the mcu stuck in totally beginning before the code of keyboard routines go execute or keyboard ISR have chance to run. The stuck will not happen only if I am comment the line with inicialization of keypressed queue. If I do the comment than everything work, I could delete the global variable usage and its definition, but ofcourse I cant read any information about keypress, because the queue doesnt exist (send and receive are in comment too).

Summary:
key_number global - should be redundant, but still defined and once somewhere! used, otherwise I must comment inicialization of keyboard, especially queuecreate cmd

variable in queuesendISR must be global otherwise the data is not put in queue

THE PROBLEM SHOULD BE SOMEWHERE IN MEMORY STUFF. Do you know what is the relation between global variables and creating dynamic queue?
I tried to change minimal stack size, size of usart queues and keypress queue (its just 3 chars) and I dont thing there is not enough memory.
The rest of code which I dont publish is pretty much the same as original example. Hope u understand my issue..
HOW IT IS POSSIBLE THAT IT WORKS ONLY IF I USE THIS USELESS GLOBAL VARIABLE? SOMETIMES I CANT EVEN CHANGE ITS NAME! I tried clean project, delete debug..

portBASE_TYPE init_keyboard(void)
{
/* Create the queue used to hold pressed keys. */
vprvKeyboardCreateQueue( KEYPRESSED_QUEUE_LENGHT, &xKeyPressed );
if( ( xKeyPressed == (xQueueHandle) 0 ) ) {
return 0;
}

// Enable edge-triggered interrupt.
eic_options[0].eic_mode = EIC_MODE_EDGE_TRIGGERED;
// Interrupt will trigger on falling edge (this is a must-do for the keypad scan
// feature if the chosen mode is edge-triggered).
eic_options[0].eic_edge = EIC_EDGE_FALLING_EDGE;
// Initialize in synchronous mode : interrupt is synchronized to the clock
eic_options[0].eic_async = EIC_SYNCH_MODE;
// Set the interrupt line number.
eic_options[0].eic_line = EXT_INT_EXAMPLE_LINE1;


// Enable edge-triggered interrupt.
eic_options[1].eic_mode = EIC_MODE_EDGE_TRIGGERED;
// Interrupt will trigger on falling edge (this is a must-do for the keypad scan
// feature if the chosen mode is edge-triggered).
eic_options[1].eic_edge = EIC_EDGE_FALLING_EDGE;
// Initialize in synchronous mode : interrupt is synchronized to the clock
eic_options[1].eic_async = EIC_SYNCH_MODE;
// Set the interrupt line number.
eic_options[1].eic_line = EXT_INT_EXAMPLE_LINE2;

// Enable edge-triggered interrupt.
eic_options[2].eic_mode = EIC_MODE_EDGE_TRIGGERED;
// Interrupt will trigger on falling edge (this is a must-do for the keypad scan
// feature if the chosen mode is edge-triggered).
eic_options[2].eic_edge = EIC_EDGE_FALLING_EDGE;
// Initialize in synchronous mode : interrupt is synchronized to the clock
eic_options[2].eic_async = EIC_SYNCH_MODE;
// Set the interrupt line number.
eic_options[2].eic_line = EXT_INT_EXAMPLE_LINE3;

// Activate LED0 & LED1 & LED2 & LED3 pins in GPIO output mode and switch them off.
gpio_tgl_gpio_pin(AVR32_PIN_PA18);

// Map the interrupt lines to the GPIO pins with the right peripheral functions.
static const gpio_map_t EIC_GPIO_MAP =
{
{EXT_INT_EXAMPLE_PIN_LINE1, EXT_INT_EXAMPLE_FUNCTION_LINE1},
{EXT_INT_EXAMPLE_PIN_LINE2, EXT_INT_EXAMPLE_FUNCTION_LINE2},
{EXT_INT_EXAMPLE_PIN_LINE3, EXT_INT_EXAMPLE_FUNCTION_LINE3},
{EXT_SCAN_EXAMPLE_PIN_LINE1, EXT_SCAN_EXAMPLE_FUNCTION_LINE1},
{EXT_SCAN_EXAMPLE_PIN_LINE2, EXT_SCAN_EXAMPLE_FUNCTION_LINE2},
{EXT_SCAN_EXAMPLE_PIN_LINE3, EXT_SCAN_EXAMPLE_FUNCTION_LINE3},
{EXT_SCAN_EXAMPLE_PIN_LINE4, EXT_SCAN_EXAMPLE_FUNCTION_LINE4},
{EXT_SCAN_EXAMPLE_PIN_LINE5, EXT_SCAN_EXAMPLE_FUNCTION_LINE5},
{EXT_SCAN_EXAMPLE_PIN_LINE6, EXT_SCAN_EXAMPLE_FUNCTION_LINE6},
{EXT_SCAN_EXAMPLE_PIN_LINE7, EXT_SCAN_EXAMPLE_FUNCTION_LINE7}
};
gpio_enable_module(EIC_GPIO_MAP, sizeof(EIC_GPIO_MAP) / sizeof(EIC_GPIO_MAP[0]));
// Enable GPIO pullups for the rows.
gpio_enable_pin_pull_up(EXT_INT_EXAMPLE_PIN_LINE1);
gpio_enable_pin_pull_up(EXT_INT_EXAMPLE_PIN_LINE2);
gpio_enable_pin_pull_up(EXT_INT_EXAMPLE_PIN_LINE3);

// Disable all interrupts.
Disable_global_interrupt();

// Initialize interrupt vectors.
INTC_init_interrupts();

// Register the EIC interrupt handler to the interrupt controller.
// eic_int_handler1 and eic_int_handler2 are the interrupt handlers to register.
// EXT_INT_EXAMPLE_IRQ_LINE1 and EXT_INT_EXAMPLE_IRQ_LINE2 are the IRQ of the
// interrupt handlers to register.
// AVR32_INTC_INT0 is the interrupt priority level to assign to the group of this IRQ.
// void INTC_register_interrupt(__int_handler handler, unsigned int irq, unsigned int int_lev);

INTC_register_interrupt(&vEIC_int_handler1_ISR, EXT_INT_EXAMPLE_IRQ_LINE1, AVR32_INTC_INT2);
INTC_register_interrupt(&vEIC_int_handler2_ISR, EXT_INT_EXAMPLE_IRQ_LINE2, AVR32_INTC_INT2);
INTC_register_interrupt(&vEIC_int_handler3_ISR, EXT_INT_EXAMPLE_IRQ_LINE3, AVR32_INTC_INT2);

/* INTC_register_interrupt(&eic_int_handler1, EXT_INT_EXAMPLE_IRQ_LINE1, AVR32_INTC_INT0);
INTC_register_interrupt(&eic_int_handler2, EXT_INT_EXAMPLE_IRQ_LINE2, AVR32_INTC_INT0);
INTC_register_interrupt(&eic_int_handler3, EXT_INT_EXAMPLE_IRQ_LINE3, AVR32_INTC_INT0);
*/
// Init the EIC controller with the options
eic_init(&AVR32_EIC, eic_options, 3);
// Enable the EIC lines.
eic_enable_lines(&AVR32_EIC, (1<<eic_options[2].eic_line)|(1<<eic_options[1].eic_line)|(1<<eic_options[0].eic_line));
// Enable the interrupt for each EIC line.
eic_enable_interrupt_lines(&AVR32_EIC, (1<<eic_options[2].eic_line)|(1<<eic_options[1].eic_line)|(1<<eic_options[0].eic_line));
// Enable the keypad scanning feature and configure the scan rate to 18ms (== pow(2,(10+1))*RCOsc).
eic_enable_interrupt_scan(&AVR32_EIC,10);

// Enable all interrupts.
Enable_global_interrupt();

return 1;
}

/*
* Create the keypress queue.
*/
static void vprvKeyboardCreateQueue( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxKeyPressed )
{
/* Create the queue used to hold keypressed characters. */
xQueueHandle xKeyPressQ = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );

/* Pass back a reference to the queue so the keyboard API file can
post/receive characters. */
*pxKeyPressed = xKeyPressQ;
}



RE: Stuck after removing unused global variable

Posted by Dave on October 22, 2008
There does not seem to be a logical explanation but if you are using FreeRTOS version 5 or higher then you need to change the call to xQueueSendFromISR() to use the new parameter format.

You may also like to try a complete rebuild to ensure the compiler is doing the right thing.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists