Andrew Lunn wrote:
I would think what you'd want to do is to provide a function to change the FIQ vector after eCos has started.

It already exists.

void cyg_interrupt_get_vsr(cyg_vector_t vector, cyg_VSR_t** vsr);

void cyg_interrupt_set_vsr(cyg_vector_t vector, cyg_VSR_t* vsr);

with the vector CYGNUM_HAL_VECTOR_FIQ.

The vsr function needs to be written in assembly and save and restore
all registers etc.

     Andrew


We implemented a similar solution for a hard-time requirement of 300us.
In our application, we read ADC values and store them away.

Here are the notes for the setup:
// **************************
// This exception handler replaces the standard FIQ handler
// located in vectors.S. It is specific for the <name changed>
// application.
//
// To use this replacement FIQ handler:
//  1) modify linker file:
//     The linker file needs to be modified so that the HAL_VSR_SET()
//     macro works correctly.
//     In the file mlt_arm_lpc2xxx_<name changed>.ldi, change:
//
//        SECTION_fixed_vectors (ram, 0x40000040, LMA_EQ_VMA)
//     to
//        SECTION_fixed_vectors (ram, 0x40000020, LMA_EQ_VMA)
//
//     This locates hal_vsr_table at 0x40000020 (on-chip RAM).
//     hal_vsr_table is not used (except we are using it now!).
//
//     this assumes running from flash with exception vector located
//     in on-chip RAM (MEMMAP=2).
//
//  2) HAL_VSR_SET
//     The initialization code needs to replace the existing FIQ
//     handler with the application specific one. This call is
//     located in hal_api_analog_init() which is called with
//     interrupts disabled (MUST!).
//
//        extern void APPFIQ (void);
//
//        /* set APPFIQ to be the FIQ handler */
//        HAL_VSR_SET(CYGNUM_HAL_VECTOR_FIQ, APPFIQ, NULL);
//
//


A timer is used to trigger the ADC to start sampling:

/* ***                              *** */
/* set up timer for 300us reading cycle */

/* Disable and reset counter */
HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_TIMER1_BASE+CYGARC_HAL_LPC2XXX_REG_TxTCR, 2);

/* set prescale register to 0 */
HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_TIMER1_BASE+CYGARC_HAL_LPC2XXX_REG_TxPR, 0);

/* clear all interrupts */
HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_TIMER1_BASE+CYGARC_HAL_LPC2XXX_REG_TxIR, 0xffffffff);

/* clear all match/capture control settings */
HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_TIMER1_BASE+CYGARC_HAL_LPC2XXX_REG_TxMCR, 0);

/*   */
HAL_READ_UINT32(CYGARC_HAL_LPC2XXX_REG_TIMER1_BASE+CYGARC_HAL_LPC2XXX_REG_TxEMR, regTemp); HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_TIMER1_BASE+CYGARC_HAL_LPC2XXX_REG_TxEMR, (2 << 4));
/* Set up match register (plus extra for first time) */
HAL_READ_UINT32(CYGARC_HAL_LPC2XXX_REG_TIMER1_BASE+CYGARC_HAL_LPC2XXX_REG_TxTC, regTemp);
HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_TIMER1_BASE+CYGARC_HAL_LPC2XXX_REG_TxMR0,
(regTemp + 17695 + 0x00ffffff)); /* add a fudge factor for initialization */

/* Enable counter */
HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_TIMER1_BASE+CYGARC_HAL_LPC2XXX_REG_TxTCR, 1);

/* ***                                                               *** */
/* set up ADC divisor                                                    */
/* enable with a divisor of 14 (-> ~4.2MHz)                              */
/* With an input clock of ~58.98MHz, this results in a clock of ~4.2MHz. */
/* turn the adc 'on'                                                     */

/* ***                                                            *** */
/* set up ADC to sample channel 0 sample dependent upon MR0 of Timer1 */

/* set the timing, enable the power */
HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_AD_BASE+CYGARC_HAL_LPC2XXX_REG_ADCR,
             (CYGARC_HAL_LPC2XXX_REG_ADCR_PDN) |       /* power enable */
(13 << 8) ); /* clkdiv (~4.2MHz) */

/* sample channel 0 */
HAL_READ_UINT32(CYGARC_HAL_LPC2XXX_REG_AD_BASE+CYGARC_HAL_LPC2XXX_REG_ADCR, regTemp);
HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_AD_BASE+CYGARC_HAL_LPC2XXX_REG_ADCR,
              ((regTemp & 0xffffff00) | (1 << 6))  );   /* channel 6 */

/* START = '110' -> MR0 of Timer1 */
HAL_READ_UINT32(CYGARC_HAL_LPC2XXX_REG_AD_BASE+CYGARC_HAL_LPC2XXX_REG_ADCR, regTemp);
HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_AD_BASE+CYGARC_HAL_LPC2XXX_REG_ADCR,
( (regTemp & (~(7<<24))) | ((6 << 24) ) ) ); /* 110 -> start MAT1.0 */


/* ***                                *** */
/* set up ADC interrupt as FIQ and enable */

/* set interrupt as FIQ */
HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_VIC_BASE+CYGARC_HAL_LPC2XXX_REG_VICINTSELECT,
              (1<<CYGNUM_HAL_INTERRUPT_AD));

/* enable interrupt */
cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_AD);


The APPFIQ code is written in assembler and just saves some stack
and calls the handler routine.




I hope this wasn't too much detail...
- Dave



--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

Reply via email to