You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
5.5 KiB
Plaintext
160 lines
5.5 KiB
Plaintext
11 years ago
|
#define mainISR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
||
|
#define mainISRTASK_LED ( 2 )
|
||
|
#define mainT5PRESCALAR ( 6 )
|
||
|
#define mainT5_SEMAPHORE_RATE ( 31250 )
|
||
|
|
||
|
static void prvISRBlockTask( void* pvParameters )
|
||
|
{
|
||
|
/* local variables marked as volatile so the compiler does not optimize them away */
|
||
|
volatile uint64_t resAcc;
|
||
|
volatile uint32_t arg1, arg2;
|
||
|
|
||
|
/* Create the semaphore used to signal this task */
|
||
|
vSemaphoreCreateBinary( xBlockSemaphore );
|
||
|
|
||
|
/* Set up timer 5 to generate an interrupt every 50 ms */
|
||
|
T5CON = 0;
|
||
|
TMR5 = 0;
|
||
|
|
||
|
/* Timer 5 is going to interrupt at 20Hz Hz. (40,000,000 / (64 * 20) */
|
||
|
T5CONbits.TCKPS = mainT5PRESCALAR;
|
||
|
PR5 = mainT5_SEMAPHORE_RATE;
|
||
|
|
||
|
/* Setup timer 5 interrupt priority to be the maximum allowed */
|
||
|
IPC6bits.T5IP = ( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||
|
|
||
|
/* Clear the interrupt as a starting condition. */
|
||
|
IFS0bits.T5IF = 0;
|
||
|
|
||
|
/* Enable the interrupt. */
|
||
|
IEC0bits.T5IE = 1;
|
||
|
|
||
|
/* Start the timer. */
|
||
|
T5CONbits.TON = 1;
|
||
|
|
||
|
arg1 = 10;
|
||
|
arg2 = 2;
|
||
|
|
||
|
for( ;; )
|
||
|
{
|
||
|
/* block on the binary semaphore given by an ISR */
|
||
|
xSemaphoreTake( xBlockSemaphore, portMAX_DELAY );
|
||
|
|
||
|
vParTestToggleLED( mainISRTASK_LED );
|
||
|
/* perform some maths operations to exercise the accumulators */
|
||
|
resAcc = resAcc * arg2 + arg1;
|
||
|
}
|
||
|
}
|
||
|
/*-----------------------------------------------------------*/
|
||
|
|
||
|
void vT5InterruptHandler( void )
|
||
|
{
|
||
|
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||
|
|
||
|
/* This function is the handler for the peripheral timer interrupt.
|
||
|
The interrupt is initially signalled in a separate assembly file
|
||
|
which switches to the system stack and then calls this function.
|
||
|
It gives a semaphore which signals the prvISRBlockTask */
|
||
|
xSemaphoreGiveFromISR( xBlockSemaphore, &xHigherPriorityTaskWoken );
|
||
|
|
||
|
/* Clear the interrupt */
|
||
|
IFS0CLR = _IFS0_T5IF_MASK;
|
||
|
|
||
|
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
|
||
|
}
|
||
|
|
||
|
/*-----------------------------------------------------------*/
|
||
|
|
||
|
#define DMA_BUFF_SIZE 400
|
||
|
uint32_t dmaBuff[2][DMA_BUFF_SIZE];
|
||
|
static void dmaTask(void* pvParameters)
|
||
|
{
|
||
|
uint32_t i;
|
||
|
/* this tasks hammers the dma copying data from one buffer to another */
|
||
|
DMACONbits.SUSPEND = 1; //Suspend ALL DMA transfers
|
||
|
|
||
|
/* currently the data will be placed in the cache and nothing will be copied
|
||
|
* by the dma as it only accesses physical memory, this test is designed to stress the system
|
||
|
* and confirm correct operation in a heavy interrupt environment */
|
||
|
for(i = 0; i < DMA_BUFF_SIZE; i++) {
|
||
|
dmaBuff[0][i] = i;
|
||
|
}
|
||
|
|
||
|
/* set the transfer event control: what event is to start the DMA transfer */
|
||
|
DCH1ECONbits.CHSIRQ = _TIMER_6_VECTOR;
|
||
|
DCH1ECONbits.SIRQEN = 1;
|
||
|
|
||
|
/* set up transfer */
|
||
|
DCH1SSA = KVA_TO_PA((void*) &dmaBuff[0][0]);
|
||
|
DCH1DSA = KVA_TO_PA((void*) &dmaBuff[1][0]);
|
||
|
DCH1SSIZ = DMA_BUFF_SIZE;
|
||
|
DCH1DSIZ = DMA_BUFF_SIZE;
|
||
|
DCH1CSIZ = 4;
|
||
|
|
||
|
/* setup interrupt response */
|
||
|
IPC33bits.DMA1IP = 3;
|
||
|
DCH1INTbits.CHBCIE = 1;
|
||
|
IEC4bits.DMA1IE = 1;
|
||
|
DCH1CONbits.CHPRI = 0b10;
|
||
|
|
||
|
/* once we configured the DMA channel we can enable it */
|
||
|
DCH1CONbits.CHEN = 1;
|
||
|
DMACONbits.ON = 1;
|
||
|
DMACONbits.SUSPEND = 0;
|
||
|
|
||
|
/* setup T6 to trigger the transfers */
|
||
|
T6CON = 0x0000;
|
||
|
IEC0CLR = _IEC0_T6IE_MASK;
|
||
|
IFS0CLR = _IFS0_T6IF_MASK;
|
||
|
TMR6 = 0;
|
||
|
PR6 = 1;
|
||
|
T6CONSET = _T6CON_ON_MASK;
|
||
|
|
||
|
/* once the dma is setup we delete this task */
|
||
|
vTaskDelete(NULL);
|
||
|
}
|
||
|
|
||
|
void __attribute__((vector(_DMA1_VECTOR), interrupt(ipl3))) DMAInterruptHandler(void)
|
||
|
{
|
||
|
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||
|
uint32_t i;
|
||
|
|
||
|
/* clear the destination buffer */
|
||
|
for(i = 0; i < DMA_BUFF_SIZE; i++) {
|
||
|
dmaBuff[1][i] = 0;
|
||
|
}
|
||
|
|
||
|
xSemaphoreGiveFromISR( xBlockSemaphore, &xHigherPriorityTaskWoken );
|
||
|
|
||
|
/* we have just finished copying from buffer0 to buffer 1 so restart the copy operation */
|
||
|
DCH1INTCLR = _DCH1INT_CHBCIF_MASK;
|
||
|
IFS4CLR = _IFS4_DMA1IF_MASK;
|
||
|
DCH1CONSET = _DCH1CON_CHEN_MASK;
|
||
|
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
|
||
|
}
|
||
|
|
||
|
/*-----------------------------------------------------------*/
|
||
|
|
||
|
* The Blinky ISR Test:
|
||
|
* This demonstrates triggering an ISR from a peripheral timer. A task is created
|
||
|
* which blocks on a semaphore. Separately a peripheral timer is set to cause an
|
||
|
* interrupt every 50ms. The ISR handler (in a separate assembly file) then
|
||
|
* releases the semaphore which causes the task to unblock and toggle an LED. This
|
||
|
* sequence tests operation of the ISR and system stack handling.
|
||
|
*
|
||
|
static void prvISRBlockTask( void *pvParameters );
|
||
|
static void dmaTask(void *pvParameters);
|
||
|
|
||
|
/* The timer 5 interrupt handler. As this interrupt uses the FreeRTOS assembly
|
||
|
entry point the IPL setting in the following function prototype has no effect. */
|
||
|
void __attribute__( (interrupt(ipl3), vector(_TIMER_5_VECTOR))) vT5InterruptWrapper( void );
|
||
|
|
||
|
/*-----------------------------------------------------------*/
|
||
|
|
||
|
/* The semaphore used to signal the ISRBlockTask */
|
||
|
static xSemaphoreHandle xBlockSemaphore;
|
||
|
|
||
|
|
||
|
// xTaskCreate( prvISRBlockTask, ( signed char * ) "ISR", configMINIMAL_STACK_SIZE, ( void * ) NULL, mainISR_TASK_PRIORITY, NULL );
|
||
|
// xTaskCreate( dmaTask, (signed char *) "DMA", configMINIMAL_STACK_SIZE, (void*) NULL, 2, NULL);
|