This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Re: On ARM7 can one of FIQ/IRQ be used for non-eCos stuff?




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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]