现在的位置: 首页 > 综合 > 正文

【学习笔记】zedboard上freertos 按键中断

2014年08月29日 ⁄ 综合 ⁄ 共 5404字 ⁄ 字号 评论关闭

代码工作流程:在freertos系统中创建一个二值信号量,并且创建两个任务,任务A:循环输出helloworld,任务B:获取二值信号量,当获取到后设置LED灯亮或灯灭,如果没有获取到则挂起,直到获取到二值信号量。设置按键中断,并在按键中断程序中释放二值信号量。

实验现象:按键按下则LED灯实现亮或灭

/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "timers.h"
#include "xil_printf.h"
#include "xscugic.h"
/* App includes. */
#include "xgpiops.h"

/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 */
#define GPIO_DEVICE_ID	XPAR_XGPIOPS_0_DEVICE_ID

/*
 * Following constant define the Input and Output pins.
 */
#define OUTPUT_PIN_LED		55	/* Pin connected to LED/Output */
#define INPUT_PIN_BTN		54	/* Pin connected to LED/Output */

/* Priorities at which the tasks are created. */
#define mainLED_TASK_PRIORITY		( tskIDLE_PRIORITY + 1 )
#define mainHELLO_WORLD_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )

/*
 * The following are declared globally so they are zeroed.
 */
static XGpioPs Gpio;	/* The driver instance for GPIO Device. */
static XScuGic *mXScuGic;

/* Task handle */
xTaskHandle xTask;

/* Semaphore handle */
xSemaphoreHandle xSemaphore_led = NULL;

/*-----------------------------------------------------------*/
static void prvLed_Task( void *pvParameters );
void prvSetGpioHardware(void);
void prvShutdown(void);
static void prvPrintf(void *pvParameters);

int main( void )
{
	 prvInitializeExceptions();

	 /* Create Binary Semaphore */
	 vSemaphoreCreateBinary(xSemaphore_led);
	 configASSERT( xSemaphore_led );

	 /* Setup the GPIO Hardware. */
	 prvSetGpioHardware();

	 xTaskCreate(prvPrintf,(signed char *)"Hello",configMINIMAL_STACK_SIZE,NULL,mainHELLO_WORLD_TASK_PRIORITY,&xTask);
	 /* Create the task */
     xTaskCreate( prvLed_Task, ( signed char * ) "LED_TASK",
     			configMINIMAL_STACK_SIZE, NULL,
    			mainLED_TASK_PRIORITY, &xTask );

     /* Starting the scheduler will start the timers running as it is already
     been set into the active state. */
     vTaskStartScheduler();

     /* Should not reach here. */
     for( ;; );
}

/*-----------------------------------------------------------*/
static void prvPrintf(void *pvParameters)
{
	const portTickType xDelay = 500 / portTICK_RATE_MS;
	for( ;; )
	{
		xil_printf("Hello World\r\n");
		vTaskDelay(xDelay);
		taskYIELD();
	}
}
/*-----------------------------------------------------------*/
static void prvLed_Task( void *pvParameters )
{
  	unsigned int uiLedFlag = 0;

	for (;;)
		{
			if ( xSemaphoreTake( xSemaphore_led,
						( portTickType ) portMAX_DELAY ) == pdTRUE )
			{
				uiLedFlag ^= 1;
				if (uiLedFlag) {
					/*
					 * Set the GPIO Output to High.
					 */
					XGpioPs_WritePin(&Gpio, OUTPUT_PIN_LED, 0x1);
				 } else {
					/*
					 * Set the GPIO Output to Low.
					 */
					XGpioPs_WritePin(&Gpio, OUTPUT_PIN_LED, 0x0);
				 }
			} else {
				xil_printf("xSemaphore_led take fail\r\n");
				/* Call shutdown */
				prvShutdown();
			}
		}
}

/*-----------------------------------------------------------*/
/*
 * GPIO ISR
 */
void vGpioPsISRHandler(void *CallBackRef,int bank,u32 Status)
{
	if(bank != 2)
		return;
	static portBASE_TYPE xHandler;
	xHandler=pdFALSE;
	XGpioPs *pXGpioPs = (XGpioPs *)CallBackRef;
	XGpioPs_IntrDisablePin(pXGpioPs,INPUT_PIN_BTN);
	xSemaphoreGiveFromISR(xSemaphore_led,&xHandler);
	if(xHandler==pdTRUE)
		xil_printf("semaphoreGive\r\n");
	XGpioPs_IntrEnablePin(pXGpioPs,INPUT_PIN_BTN);
}

void prvSetGpioHardware( void )
{
 	int Status;
 	XGpioPs_Config *ConfigPtr; /* The driver config instance for GPIO Device. */
 	/*
 	 * Initialize the GPIO driver.
 	 */
 	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
 	Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr,
 					ConfigPtr->BaseAddr);
 	if (Status != XST_SUCCESS) {
 		xil_printf("GPIO Initialize failed\n");
 	}

 	/*
 	 * Set the direction for the pin to be output and
 	 * Enable the Output enable for the LED Pin.
 	 */
 	XGpioPs_SetDirectionPin(&Gpio,INPUT_PIN_BTN,0);
 	XGpioPs_SetDirectionPin(&Gpio, OUTPUT_PIN_LED, 1);
 	XGpioPs_SetOutputEnablePin(&Gpio, OUTPUT_PIN_LED, 1);

 	/*
 	 * Set the GPIO output to be low.
 	 */
 	XGpioPs_WritePin(&Gpio, OUTPUT_PIN_LED, 0x0);

 	/*
 	 * SET BTN INTR
 	 */
 	XGpioPs_SetIntrTypePin(&Gpio,INPUT_PIN_BTN,XGPIOPS_IRQ_TYPE_EDGE_RISING);
 	XGpioPs_SetCallbackHandler(&Gpio,(void*)&Gpio,vGpioPsISRHandler);
 	XGpioPs_IntrEnablePin(&Gpio,INPUT_PIN_BTN);
}

void prvShutdown( void )
{
	 vSemaphoreDelete( xSemaphore_led );
	 vTaskDelete( xTask );
}

/*-----------------------------------------------------------*/
void vApplicationMallocFailedHook( void )
{
	/* vApplicationMallocFailedHook() will only be called if
	configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h.  It is a hook
	function that will get called if a call to pvPortMalloc() fails.
	pvPortMalloc() is called internally by the kernel whenever a task, queue or
	semaphore is created.  It is also called by various parts of the demo
	application.  If heap_1.c or heap_2.c are used, then the size of the heap
	available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
	FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
	to query the size of free heap space that remains (although it does not
	provide information on how the remaining heap might be fragmented). */
	taskDISABLE_INTERRUPTS();
	for( ;; );
}

/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName )
{
	( void ) pcTaskName;
	( void ) pxTask;

	/* vApplicationStackOverflowHook() will only be called if
	configCHECK_FOR_STACK_OVERFLOW is set to either 1 or 2.  The handle and name
	of the offending task will be passed into the hook function via its
	parameters.  However, when a stack has overflowed, it is possible that the
	parameters will have been corrupted, in which case the pxCurrentTCB variable
	can be inspected directly. */
	taskDISABLE_INTERRUPTS();
	for( ;; );
}

/*
 *  GPIO GIC INIT
 */
void vApplicationSetupHardware( void )
{
	mXScuGic = (XScuGic *)prvGetInterruptControllerInstance();

	XScuGic_Disable(mXScuGic,XPAR_XGPIOPS_0_INTR);
	XScuGic_SetPriorityTriggerType(mXScuGic,XPAR_XGPIOPS_0_INTR,0x02,0x01);
	XScuGic_Connect(mXScuGic,XPAR_XGPIOPS_0_INTR,(Xil_ExceptionHandler)XGpioPs_IntrHandler,(void*)&Gpio);
	XScuGic_Enable(mXScuGic,XPAR_XGPIOPS_0_INTR);
}

抱歉!评论已关闭.