This is the mail archive of the
ecos-discuss@sourceware.org
mailing list for the eCos project.
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