Mercurial > ecos-v3_0-branch
changeset 2586:b147c0c67463
* cdl/hal_arm_lpc24xx.cdl: Added configuration options for ADC
clock and RTC clock
* include/lpc24xx_misc.h Added macros CYG_HAL_ARM_LPC24XX_PCLK() and
CYG_HAL_ARM_LPC24XX_SET_POWER() for configuring on-chip peripherals
Added CYG_HAL_ARM_LPC24XX_PIN_CFG() for configuration of pin function
* src/lpc24xx_misc.c: Changed function hal_delay_us() to use the same
timer (timer 0) like the eCos realtime clock. This safes one timer
peripheral for application use.
Fixed wrong clock divider table in hal_lpc_set_pclk(). Added ADC and
RTC clock divider configuration and power on.
| author | asl |
|---|---|
| date | Tue, 04 Nov 2008 16:19:37 +0000 |
| parents | 2f250a337a5e |
| children | 2f467aabb085 |
| files | packages/hal/arm/lpc24xx/var/current/ChangeLog packages/hal/arm/lpc24xx/var/current/cdl/hal_arm_lpc24xx.cdl packages/hal/arm/lpc24xx/var/current/include/lpc24xx_misc.h packages/hal/arm/lpc24xx/var/current/include/var_io.h packages/hal/arm/lpc24xx/var/current/src/lpc24xx_misc.c |
| diffstat | 5 files changed, 217 insertions(+), 62 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/hal/arm/lpc24xx/var/current/ChangeLog +++ b/packages/hal/arm/lpc24xx/var/current/ChangeLog @@ -1,3 +1,16 @@ +2008-11-01 Uwe Kindler <uwe_kindler@web.de> + + * cdl/hal_arm_lpc24xx.cdl: Added configuration options for ADC + clock and RTC clock + * include/lpc24xx_misc.h Added macros CYG_HAL_ARM_LPC24XX_PCLK() and + CYG_HAL_ARM_LPC24XX_SET_POWER() for configuring on-chip peripherals + Added CYG_HAL_ARM_LPC24XX_PIN_CFG() for configuration of pin function + * src/lpc24xx_misc.c: Changed function hal_delay_us() to use the same + timer (timer 0) like the eCos realtime clock. This safes one timer + peripheral for application use. + Fixed wrong clock divider table in hal_lpc_set_pclk(). Added ADC and + RTC clock divider configuration and power on. + 2008-09-18 Uwe Kindler <uwe_kindler@web.de> * cdl/hal_arm_lpc24xx.cdl: Added I2C configuration options for
--- a/packages/hal/arm/lpc24xx/var/current/cdl/hal_arm_lpc24xx.cdl +++ b/packages/hal/arm/lpc24xx/var/current/cdl/hal_arm_lpc24xx.cdl @@ -241,15 +241,17 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX { legal_values 1 to 8 default_value { 6 } description " - This divider controls the division of the PLL output before - it is used by the USB block. If the PLL is bypassed, the - division may be by 1. In that case, the PLL input frequency - must be 48 MHz, with a 500 ppm tolerance. When the PLL is - running, the output must be divided in order to bring the - USB clock frequency to 48 MHz with a 50% duty cycle. A - 4-bit divider allows obtaining the correct USB clock from - any even multiple of 48 MHz (i.e. any mutliple of 96 MHz) - within the PLL operating range." + This divider controls the division of the PLL + output before it is used by the USB block. If the + PLL is bypassed, the division may be by 1. In that + case, the PLL input frequency must be 48 MHz, with + a 500 ppm tolerance. When the PLL is running, the + output must be divided in order to bring the USB + clock frequency to 48 MHz with a 50% duty cycle. A + 4-bit divider allows obtaining the correct USB + clock from any even multiple of 48 MHz (i.e. any + mutliple of 96 MHz) within the PLL operating + range." } } @@ -274,7 +276,49 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX { } } - for { set ::channel 0 } { $::channel < 3 } { incr ::channel } { + cdl_component CYGNUM_HAL_ARM_LPC24XX_RTC_CLK { + display "RTC clock speed" + flavor data + calculated { CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED / + CYGNUM_HAL_ARM_LPC24XX_RTC_CLK_DIV} + description " + The RTC clock speed is the CPU clock output divided by the + RTC clock divider" + + cdl_option CYGNUM_HAL_ARM_LPC24XX_RTC_CLK_DIV { + display "RTC clock divider" + flavor data + legal_values { 2 4 8 } + default_value { 2 } + description " + This divider selects the peripheral clock for on-chip + RTC if no external 32.768 kHz crystal clock for the + on-chip real-time clock peripheral unit is provided." + } + } + + cdl_component CYGNUM_HAL_ARM_LPC24XX_ADC_CLK { + display "ADC clock speed" + flavor data + calculated { CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED / + CYGNUM_HAL_ARM_LPC24XX_ADC_CLK_DIV} + description " + The ADC clock speed is the CPU clock output divided by the + ADC clock divider" + + cdl_option CYGNUM_HAL_ARM_LPC24XX_ADC_CLK_DIV { + display "ADC clock divider" + flavor data + legal_values { 1 2 4 8 } + default_value { 1 } + description " + This divider selects the peripheral clock for on-chip + ADC. The ADC clock is the input clock of the ADC + peripheral." + } + } + + for { set ::channel 0 } { $::channel < 3 } { incr ::channel } { cdl_component CYGNUM_HAL_ARM_LPC24XX_I2C[set ::channel]_CLK { display "I2C channel [set ::channel] clock speed" flavor data @@ -302,6 +346,7 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX { cdl_component CYGHWR_HAL_ARM_LPC24XX_I2C[set ::channel]_SUPP { display "I2C channel [set ::channel] configuration" parent CYGPKG_DEVS_I2C_ARM_LPC2XXX + active_if CYGPKG_DEVS_I2C_ARM_LPC2XXX flavor bool default_value [set ::channel] == 0 description " @@ -319,7 +364,7 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX { interrupt priority registers defaults all interrupts to the lowest priority 15, allowing a single write to elevate the priority of an - individual interrupt." + individual interrupt." } cdl_option CYGNUM_HAL_ARM_LPC24XX_I2C[set ::channel]_BUS_FREQ {
--- a/packages/hal/arm/lpc24xx/var/current/include/lpc24xx_misc.h +++ b/packages/hal/arm/lpc24xx/var/current/include/lpc24xx_misc.h @@ -55,6 +55,7 @@ // Use PCLK identifiers below // externC cyg_uint32 hal_lpc_get_pclk(cyg_uint32 pclk_id); +#define CYG_HAL_ARM_LPC24XX_PCLK(_pclkid_) hal_lpc_get_pclk(_pclkid_) // // Identifiers for peripheral clock. Use these identifiers with the function @@ -96,6 +97,9 @@ externC cyg_uint32 hal_lpc_get_pclk(cyg_ // Use PCONP identifiers from below // externC void hal_lpc_set_power(cyg_uint8 pconp_id, int on); +#define CYG_HAL_ARM_LPC24XX_SET_POWER(_pconp_id_, _on_) \ + hal_lpc_set_power((_pconp_id_), (_on_)) + // // Identifiers for power control @@ -133,7 +137,10 @@ externC void hal_lpc_set_power(cyg_uint8 //----------------------------------------------------------------------------- // Configure pin function // -void hal_set_pin_function(cyg_uint8 port, cyg_uint8 pin, cyg_uint8 function); +externC void hal_set_pin_function(cyg_uint8 port, cyg_uint8 pin, + cyg_uint8 function); +#define CYG_HAL_ARM_LPC24XX_PIN_CFG(_port_, _pin_, _func_) \ + hal_set_pin_function((_port_), (_pin_), (_func_)) //----------------------------------------------------------------------------- @@ -143,7 +150,6 @@ void hal_set_pin_function(cyg_uint8 port // Now we rely on the fact that we use the same baudrate clock for all // UARTs and we query only UART0 //----------------------------------------------------------------------------- -#define CYG_HAL_ARM_LPC24XX_PCLK(_pclkid_) hal_lpc_get_pclk(_pclkid_) #define CYG_HAL_ARM_LPC2XXX_BAUD_GENERATOR(baud) \ (CYG_HAL_ARM_LPC24XX_PCLK(CYNUM_HAL_LPC24XX_PCLK_UART0)/((baud)*16)) #define CYG_HAL_ARM_LPC24XX_BAUD_GENERATOR(_pclkid_, baud) \
--- a/packages/hal/arm/lpc24xx/var/current/include/var_io.h +++ b/packages/hal/arm/lpc24xx/var/current/include/var_io.h @@ -351,6 +351,8 @@ // RTC #define CYGARC_HAL_LPC24XX_REG_RTC_BASE 0xE0024000 +#define CYGARC_HAL_LPC2XXX_REG_RTC_BASE 0xE0024000 + // Registers are offsets from base of this subsystem @@ -483,8 +485,8 @@ //============================================================================= // ADC (AD) - #define CYGARC_HAL_LPC24XX_REG_AD_BASE 0xE0034000 +#define CYGARC_HAL_LPC2XXX_REG_AD_BASE CYGARC_HAL_LPC24XX_REG_AD_BASE // Registers are offsets from base of this subsystem #define CYGARC_HAL_LPC24XX_REG_ADCR 0x0000
--- a/packages/hal/arm/lpc24xx/var/current/src/lpc24xx_misc.c +++ b/packages/hal/arm/lpc24xx/var/current/src/lpc24xx_misc.c @@ -75,6 +75,9 @@ #include <cyg/infra/diag.h> // For diagnostic printing +static cyg_uint32 clock_period = 0; + + //=========================================================================== // Get peripheral clock for a certain peripheral //=========================================================================== @@ -115,9 +118,13 @@ cyg_uint32 hal_lpc_get_pclk(cyg_uint32 p //=========================================================================== void hal_lpc_set_pclk(cyg_uint32 peripheral_id, cyg_uint8 divider) { - static const cyg_uint8 clock_tbl[4] = + static const cyg_uint8 clock_tbl[5] = { - 0x01, 0x02, 0x00, 0x03 + 0x01, // divider 1 + 0x02, // divider 2 + 0x00, // divider 4 + 0x03, // divider 6 + 0x03 // divider 8 }; cyg_uint32 clock; cyg_uint32 pclkselreg; @@ -134,7 +141,6 @@ void hal_lpc_set_pclk(cyg_uint32 periphe CYGARC_HAL_LPC24XX_REG_PCLKSEL0 : CYGARC_HAL_LPC24XX_REG_PCLKSEL1; HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + pclkselreg, regval); - divider = (6 == divider) ? 8 : divider; clock = clock_tbl[divider >> 1]; regval &= ~(0x03 << ((peripheral_id & 0xF) << 1)); regval |= (clock << ((peripheral_id & 0xF) << 1)); @@ -189,30 +195,61 @@ void hal_set_pin_function(cyg_uint8 port //=========================================================================== +// Start clock of RTC timer +//=========================================================================== +void hal_start_clock_tmr(cyg_uint32 period) +{ + if (clock_period == period) + { + return; + } + + + cyg_uint32 tmr_period = period / (CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED / + hal_lpc_get_pclk(CYNUM_HAL_LPC24XX_PCLK_TIMER0)); + + // + // Execute the following steps only if counter is not running yet + // + if (!clock_period) + { + // + // Disable and reset counter, set prescale register to 0 and + // Set up match register + // + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxTCR, 2); + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxPR, 0); + } + + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxMR0, tmr_period); + // + // Reset on match and Enable counter - interrupts are disabled + // + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxMCR, + CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_RESET); + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxTCR, 1); +} + + +//=========================================================================== // initialize timer 0 as eCos realtime clock source //=========================================================================== void hal_clock_initialize(cyg_uint32 period) { - CYG_ADDRESS timer = CYGARC_HAL_LPC24XX_REG_TIMER0_BASE; - - period = period / (CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED / - hal_lpc_get_pclk(CYNUM_HAL_LPC24XX_PCLK_TIMER0)); - - // - // Disable and reset counter, set prescale register to 0 and - // Set up match register - // - HAL_WRITE_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxTCR, 2); - HAL_WRITE_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxPR, 0); - HAL_WRITE_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxMR0, period); + hal_start_clock_tmr(period); // - // Reset and generate interrupt on match and Enable counter + // Reset and generate interrupt on match // - HAL_WRITE_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxMCR, + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxMCR, CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_INT | CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_RESET); - HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxTCR, 1); } @@ -221,22 +258,20 @@ void hal_clock_initialize(cyg_uint32 per //=========================================================================== void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period) { - static cyg_uint32 _period = 0; - CYG_ADDRESS timer = CYGARC_HAL_LPC24XX_REG_TIMER0_BASE; - - HAL_WRITE_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxIR, + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxIR, CYGARC_HAL_LPC24XX_REG_TxIR_MR0); // Clear interrupt - if (period != _period) + if (period != clock_period) { hal_clock_initialize(period); } - _period = period; + clock_period = period; } //=========================================================================== -// Reset clock value +// Read clock value //=========================================================================== void hal_clock_read(cyg_uint32 *pvalue) { @@ -249,40 +284,77 @@ void hal_clock_read(cyg_uint32 *pvalue) //=========================================================================== -// Delay for some number of micro-seconds - use TIMER1 +// Delay for maximum 1000 micorseconds //=========================================================================== -void hal_delay_us(cyg_int32 usecs) +static void delay_max1000_us(cyg_uint32 usecs) { - CYG_ADDRESS timer = CYGARC_HAL_LPC24XX_REG_TIMER1_BASE; - cyg_uint32 stat; - cyg_uint64 ticks; + cyg_uint32 ticks; + cyg_uint32 start_counter; + cyg_uint32 target_counter; + cyg_uint32 counter; + cyg_uint32 tmr_period; + + CYG_ASSERT((usecs <= 1000) && (usecs > 0), "Invalid usecs value"); + HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxTC, start_counter); + + HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxMR0, tmr_period); + + // + // If timer 0 match period is not initialized, then this is the + // first time that someone uses the timer and we need to initialize it + // + if (!tmr_period) + { + hal_start_clock_tmr(CYGNUM_HAL_RTC_PERIOD); + HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxMR0, tmr_period); + } + // Calculate how many timer ticks the required number of // microseconds equate to. We do this calculation in 64 bit // arithmetic to avoid overflow. ticks = (((cyg_uint64)usecs) * - ((cyg_uint64)hal_lpc_get_pclk(CYNUM_HAL_LPC24XX_PCLK_TIMER1))) / + ((cyg_uint64)hal_lpc_get_pclk(CYNUM_HAL_LPC24XX_PCLK_TIMER0))) / 1000000LL; - - // Disable and reset counter - HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxTCR, 2); + + target_counter = (start_counter + ticks) % tmr_period; - // Stop on match - HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxMR0, ticks); - HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxMCR, - CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_STOP | - CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_RESET); + if (target_counter > start_counter) + { + do + { + HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxTC, counter); + } while ((counter >= start_counter) && (counter < target_counter)); + } + else + { + do + { + HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_TIMER0_BASE + + CYGARC_HAL_LPC24XX_REG_TxTC, counter); + } while ((counter >= start_counter) || (counter < target_counter)); + } // if (target_counter > start_counter) +} - //set prescale register to 0 - HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxPR, 0); - // Enable counter - HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxTCR, 1); +//=========================================================================== +// Delay for a certain numbr of microseconds +//=========================================================================== +void hal_delay_us(cyg_int32 usecs) +{ + cyg_uint16 delay_duration = usecs % 1000; + delay_duration = (delay_duration != 0) ? delay_duration : 1000; - // Wait for the match - do { - HAL_READ_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxTC, stat); - } while (stat < ticks); + do + { + delay_max1000_us(delay_duration); + usecs -= delay_duration; + delay_duration = 1000; + } while (usecs > 0); } @@ -309,6 +381,10 @@ void hal_hardware_init(void) CYGNUM_HAL_ARM_LPC24XX_I2C1_CLK_DIV); hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_I2C2, CYGNUM_HAL_ARM_LPC24XX_I2C2_CLK_DIV); + hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_RTC, + CYGNUM_HAL_ARM_LPC24XX_RTC_CLK_DIV); + hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_ADC, + CYGNUM_HAL_ARM_LPC24XX_ADC_CLK_DIV); // // Enable power for all used on-chip peripherals @@ -329,7 +405,20 @@ void hal_hardware_init(void) hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_I2C2, 1); #else hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_I2C2, 0); -#endif // CYGHWR_HAL_ARM_LPC24XX_I2C0_SUPP +#endif // CYGHWR_HAL_ARM_LPC24XX_I2C0_SUPP + +#ifdef CYGPKG_DEVICES_WALLCLOCK_ARM_LPC2XXX + hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_RTC, 1); +#else + hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_RTC, 0); +#endif // CYGPKG_DEVICES_WALLCLOCK_ARM_LPC2XXX + +#ifdef CYGPKG_DEVS_ADC_ARM_LPC24XX + hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_ADC, 1); + hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_TIMER1, 1); +#else + hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_ADC, 0); +#endif // CYGPKG_DEVS_ADC_ARM_LPC24XX // // Fill vector address registers with interrupt number. If an interrupt
