changeset 2511:1f18f909a18e

* src/lpc2xxx_misc.c: Added hal_lpc_can_init() to initialize CAN channels * cdl/hal_arm_lpc24xx.cdl: Added a number of CYGHWR_HAL_ARM_LPC2XXX_xxx options for device driver compatibility reasons. Some LPC2xxx device drivers rely on these definitions. Moved some configuration options to make configuration more intuitive in configuration tool. Added CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK option for configuration of CAN peripheral clock. * include/var_io.h: Added macro CYGARC_HAL_LPC24XX_SET_PIN_FUN() * src/lpc2xxx_misc.c: Added function hal_lpc_set_pclk() to set peripheral clocks easily. Initialize peripheral clocks in hal_hardware_init() according to configuration.
author asl
date Fri, 25 Jul 2008 11:14:39 +0000
parents 0c2a776fc7f4
children be7755f32fd0
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/var_arch.h packages/hal/arm/lpc24xx/var/current/include/var_io.h packages/hal/arm/lpc24xx/var/current/src/hal_diag.c packages/hal/arm/lpc24xx/var/current/src/lpc24xx_misc.c
diffstat 6 files changed, 184 insertions(+), 66 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,18 @@
+2008-07-21  Uwe Kindler  <uwe_kindler@web.de>
+
+	* src/lpc2xxx_misc.c: Added hal_lpc_can_init() to initialize CAN
+	channels
+	* cdl/hal_arm_lpc24xx.cdl: Added a number of CYGHWR_HAL_ARM_LPC2XXX_xxx
+	options for device driver compatibility reasons. Some LPC2xxx device
+	drivers rely on these definitions. Moved some configuration options
+	to make configuration more intuitive in configuration tool. Added
+	CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK option for configuration of CAN 
+	peripheral clock.
+	* include/var_io.h: Added macro CYGARC_HAL_LPC24XX_SET_PIN_FUN()
+	* src/lpc2xxx_misc.c: Added function hal_lpc_set_pclk() to set
+	peripheral clocks easily. Initialize peripheral clocks in
+	hal_hardware_init() according to configuration.
+	
 2008-07-06  Uwe Kindler  <uwe_kindler@web.de>
 
 	* Initial release of LPC24xx variant support (based on LPX2xxx variant)
--- a/packages/hal/arm/lpc24xx/var/current/cdl/hal_arm_lpc24xx.cdl
+++ b/packages/hal/arm/lpc24xx/var/current/cdl/hal_arm_lpc24xx.cdl
@@ -99,6 +99,48 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX {
                 available in the HAL."
         }
     }
+    
+    # This is going to get really messy before long as the number of parts
+    # explodes. Its useful to know the actual part in use, but its just as
+    # useful to know which family it belongs to. LPC210x shouldn't really
+    # be in the list of devices, but will probably break something if removed.
+    cdl_component CYGHWR_HAL_ARM_LPC2XXX {
+        display        "LPC2XXX variant used"
+        flavor         data
+        calculated     CYGHWR_HAL_ARM_LPC24XX
+        description    "
+             This option is only here for compatibility reasons because some of
+             the LPC2XXX device drivers rely on these definitions. If this
+             is defined here, the LPC24XX variant can use the LPC2XXX device
+             drivers for on-chip peripherals."
+
+        cdl_option CYGHWR_HAL_ARM_LPC2XXX_FAMILY {
+            display       "LPC2XXX variant family"
+            flavor        data
+            calculated    CYGHWR_HAL_ARM_LPC24XX_FAMILY
+            description   "
+                 This option is only here for compatibility reasons
+                 because some of the LPC2XXX device drivers rely on
+                 these definitions. If this is defined here, the
+                 LPC24XX variant can use the LPC2XXX device drivers
+                 for on-chip peripherals."
+        }
+        
+        cdl_option CYGHWR_HAL_ARM_LPC2XXX_VARIANT_VERSION {
+            display       "LPC2XXX variant version"
+            flavor        data
+            calculated    {
+                is_substr(CYGHWR_HAL_ARM_LPC2XXX, "LPC21") ? 1 :
+                is_substr(CYGHWR_HAL_ARM_LPC2XXX, "LPC22") ? 2 :
+                is_substr(CYGHWR_HAL_ARM_LPC2XXX, "LPC24") ? 4 : 0
+                          }
+            description   "
+                This specifies the variant version that the processor
+                belongs to. Some common characteristics may be 
+                different in newer LPC2xxx versions. I.e. the LPC24xx variants
+                are significant different from former LPC2xxx variants." 
+        }
+    }
 
     # Important! Be very careful changing this value. That will always
     # enter the LPC24XX bootloader after reset and consequently will
@@ -142,54 +184,14 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX {
             legal_values   275000000 to 290000000
             calculated {  2 * CYGNUM_HAL_ARM_LPC24XX_PLL_MUL * 
                           CYGNUM_HAL_ARM_LPC24XX_XTAL_FREQ / 
-                          CYGNUM_HAL_ARM_LPC24XX_PLL_DIV }
-            description "
-                Normally the PLL output must be in the range of 275
-                MHz to 550 MHz. Because of a chip errata the maximum
-                output of the CCO within the PLL block is limited to
-                290 MHz."
-
-        }
-        
-        cdl_option CYGNUM_HAL_ARM_LPC24XX_CPU_CLK_DIV {
-            display       "CPU clock divider"
-            flavor        data
-            legal_values  6 to 256
-            default_value { 6 }
+                          CYGNUM_HAL_ARM_LPC24XX_PLL_DIV}
             description "
-                The CPU clock divider controls the division of the PLL
-                output before it is used by the CPU. When the PLL is
-                bypassed, the division may be by 1.  When the PLL is
-                running, the output must be divided in order to bring
-                the CPU clock frequency (CCLK) within operating
-                limits. An 8 bit divider allows a range of options,
-                including slowing CPU operation to a low rate for
-                temporary power savings without turning off the
-                PLL. Only even values (2, 4, 6, ..., 256) are
-                supported and can be used. Warning: Using an odd value
-                (1, 3, 5, ..., 255) when setting this option may
-                result in incorrect operation of the device."
-         }
-    
-        cdl_option CYGNUM_HAL_ARM_LPC24XX_USB_CLK_DIV {
-            display       "USB clock divider"
-            flavor        data
-            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 multiple of 96 MHz) within the PLL
-                operating range."
+                Normally the PLL output must be in the range of 275 MHz to 
+                550 MHz Because of a chip errata the maximum output of the CCO 
+                within the PLL block is limited to 290 MHz."
         }
-        
-        cdl_option CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED {
+       
+        cdl_component CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED {
             display       "CPU clock speed"
             flavor        data
             calculated {  2 * CYGNUM_HAL_ARM_LPC24XX_PLL_MUL * 
@@ -198,10 +200,31 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX {
                           CYGNUM_HAL_ARM_LPC24XX_CPU_CLK_DIV}
             description "
                 The core CPU clock speed is the PLL output divided by the 
-                CPU clock divider"     
+                CPU clock divider" 
+                
+            cdl_option CYGNUM_HAL_ARM_LPC24XX_CPU_CLK_DIV {
+                display       "CPU clock divider"
+                flavor        data
+                legal_values  6 to 256
+                default_value { 6 }
+                description "
+                    The CPU clock divider controls the division of the PLL 
+                    output before it is used by the CPU. When the PLL is 
+                    bypassed, the division may be by 1. When the PLL is 
+                    running, the output must be divided in order to bring the 
+                    CPU clock frequency (CCLK) within operating limits. An 8 
+                    bit divider allows a range of options, including slowing 
+                    CPU operation to a low rate for temporary power savings 
+                    without turning off the PLL. Only even values 
+                    (2, 4, 6, ..., 256) are supported and can be used. 
+                    Warning: Using an odd value (1, 3, 5, ..., 255) when 
+                    setting this option may result in incorrect operation of 
+                    the device."
+             }    
         }
     
-        cdl_option CYGNUM_HAL_ARM_LPC24XX_USB_CLOCK_SPEED {
+        
+        cdl_component CYGNUM_HAL_ARM_LPC24XX_USB_CLOCK_SPEED {
             display       "USB clock speed"
             flavor        data
             calculated {  2 * CYGNUM_HAL_ARM_LPC24XX_PLL_MUL * 
@@ -211,9 +234,47 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX {
             description "
                 The USB clock speed is the PLL output divided by the 
                 USB clock divider" 
+                
+            cdl_option CYGNUM_HAL_ARM_LPC24XX_USB_CLK_DIV {
+                display       "USB clock divider"
+                flavor        data
+                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."
+            }
         }
+        
+        cdl_component CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK {
+            display       "CAN clock speed"
+            flavor        data
+            calculated   {  CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED / 
+                            CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV}
+            description "
+                The CAN clock speed is the CPU clock output divided by the 
+                CAN clock divider" 
+                
+            cdl_option CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV {
+                display       "CAN clock divider"
+                flavor        data
+                legal_values  { 1 2 4 6 }
+                default_value { 1 }
+                description "
+                    This divider selects the peripheral clock for both CAN 
+                    channels. The divider divides the CPU clock to get the 
+                    clock for the CAN peripherals."
+            }
+        }      
     }
-
+    
     cdl_component CYGNUM_HAL_RTC_CONSTANTS {
         display       "Real-time clock constants"
         flavor        none
@@ -261,4 +322,5 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX {
             lowest priority, allowing a single write to elevate the priority 
             of an individual interrupt."
     }
+
 }
--- a/packages/hal/arm/lpc24xx/var/current/include/var_arch.h
+++ b/packages/hal/arm/lpc24xx/var/current/include/var_arch.h
@@ -53,6 +53,8 @@
 
 #include <pkgconf/hal.h>
 #include <cyg/hal/hal_io.h>
+#include <cyg/infra/cyg_type.h>
+
 //--------------------------------------------------------------------------
 // Idle thread code.
 // This macro is called in the idle thread loop, and gives the HAL the
--- a/packages/hal/arm/lpc24xx/var/current/include/var_io.h
+++ b/packages/hal/arm/lpc24xx/var/current/include/var_io.h
@@ -463,6 +463,8 @@
 #define CYGARC_HAL_LPC24XX_REG_PINMODE8                  0x060
 #define CYGARC_HAL_LPC24XX_REG_PINMODE9                  0x064
 
+#define CYGARC_HAL_LPC24XX_SET_PIN_FUN(_regval_, _pin_, _func_) \
+    (_regval_) = ((_regval_) & ~(0x3 << ((_pin_) << 1))) | ((_func_) << ((_pin_) << 1))
 
 
 //=============================================================================
--- a/packages/hal/arm/lpc24xx/var/current/src/hal_diag.c
+++ b/packages/hal/arm/lpc24xx/var/current/src/hal_diag.c
@@ -303,24 +303,24 @@ static int cyg_hal_plf_serial_isr(void *
     cyg_uint8 iir;
     
     CYGARC_HAL_SAVE_GP();
-    
+
     *__ctrlc = 0;
-    
+
     HAL_READ_UINT32(chan->base + CYGARC_HAL_LPC24XX_REG_UxIIR, iir);
     
     if((iir & (CYGARC_HAL_LPC24XX_REG_UxIIR_IIR0 | 
                CYGARC_HAL_LPC24XX_REG_UxIIR_IIR1 | 
                CYGARC_HAL_LPC24XX_REG_UxIIR_IIR2)) 
        == CYGARC_HAL_LPC24XX_REG_UxIIR_IIR2)
-      {
+    {
         // Rx data available or character timeout
         // Read data in order to clear interrupt
         HAL_READ_UINT32(chan->base + CYGARC_HAL_LPC24XX_REG_UxRBR, c);
         if( cyg_hal_is_break( &c , 1 ) ) *__ctrlc = 1;
-        
+
         res = CYG_ISR_HANDLED;
     }
-    
+
     HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector);
 
     CYGARC_HAL_RESTORE_GP();
--- a/packages/hal/arm/lpc24xx/var/current/src/lpc24xx_misc.c
+++ b/packages/hal/arm/lpc24xx/var/current/src/lpc24xx_misc.c
@@ -92,8 +92,8 @@ cyg_uint32 hal_lpc_get_pclk(cyg_uint32 p
     // decide if we need PCLKSEL0 or PCLKSEL1
     //
     pclkselreg = ((peripheral_id <= CYNUM_HAL_LPC24XX_PCLK_ACF) ? 
-                  CYGARC_HAL_LPC24XX_REG_PCLKSEL0 : 
-                  CYGARC_HAL_LPC24XX_REG_PCLKSEL1); 
+                   CYGARC_HAL_LPC24XX_REG_PCLKSEL0 : 
+                   CYGARC_HAL_LPC24XX_REG_PCLKSEL1); 
     HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + pclkselreg, regval);
     regval  = (regval >> ((peripheral_id & 0xF) << 1)) & 0x03;
     divider = divider_tbl[regval];    
@@ -107,7 +107,35 @@ cyg_uint32 hal_lpc_get_pclk(cyg_uint32 p
 
 
 //===========================================================================
-// initialize timer 0 as eCos real time clock source
+// Set peripheral clock
+//===========================================================================
+void hal_lpc_set_pclk(cyg_uint32 peripheral_id, cyg_uint8 divider)
+{
+    static const cyg_uint8 clock_tbl[4] =
+    {
+        0x01, 0x02, 0x00, 0x03
+    }; 
+    cyg_uint32 clock;
+    cyg_uint32 pclkselreg;
+    cyg_uint32 regval;
+     
+    CYG_ASSERT(divider <= 8, "Wrong peripheral clock divider value"); 
+    //
+    // decide if we need PCLKSEL0 or PCLKSEL1
+    //
+    pclkselreg = (peripheral_id <= CYNUM_HAL_LPC24XX_PCLK_ACF) ? 
+                  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 |= (clock << ((peripheral_id & 0xF) << 1));   
+    HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + pclkselreg, regval);             
+}
+
+
+//===========================================================================
+// initialize timer 0 as eCos realtime clock source
 //===========================================================================
 void hal_clock_initialize(cyg_uint32 period)
 {
@@ -179,8 +207,8 @@ void hal_delay_us(cyg_int32 usecs)
     // 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)))
-      / 1000000LL;
+             ((cyg_uint64)hal_lpc_get_pclk(CYNUM_HAL_LPC24XX_PCLK_TIMER1))) / 
+               1000000LL;
     
     // Disable and reset counter
     HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxTCR, 2);
@@ -192,7 +220,7 @@ void hal_delay_us(cyg_int32 usecs)
                      CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_RESET);
 
     //set prescale register to 0
-    HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxPR, 0);			
+    HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxPR, 0);         
 
     // Enable counter
     HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxTCR, 1);
@@ -210,14 +238,22 @@ void hal_delay_us(cyg_int32 usecs)
 //===========================================================================
 void hal_hardware_init(void)
 {
-    cyg_uint32 i;  
+    cyg_uint32 i; 
+    
+    //
+    // Setup peripheral clocks here according to configuration
+    // 
+    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_CAN1, CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV);
+    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_CAN2, CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV);
+    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_ACF,  CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV);
+    
     //
     // Fill vector address registers with interrupt number. If an interrupt
     // occurs we can simply read the interrupt number from the vector
     // address register later
     //
-    cyg_uint32 addr = (CYGARC_HAL_LPC24XX_REG_VIC_BASE + 
-                       CYGARC_HAL_LPC24XX_REG_VICVECTADDR0);    
+    cyg_uint32 addr = CYGARC_HAL_LPC24XX_REG_VIC_BASE + 
+                      CYGARC_HAL_LPC24XX_REG_VICVECTADDR0;    
     for (i = 0; i < 32; ++i)
     {
         HAL_WRITE_UINT32(addr, i);
@@ -249,7 +285,7 @@ int hal_IRQ_handler(void)
 
 
 //===========================================================================
-// Block the the interrupt associated with the vector
+// Block the interrupt associated with the vector
 //===========================================================================
 void hal_interrupt_mask(int vector)
 {
@@ -312,7 +348,7 @@ void hal_interrupt_configure(int vector,
 {
     cyg_uint32 regval;
 
-    // Only external interrupts are configurable	
+    // Only external interrupts are configurable    
     CYG_ASSERT(vector <= CYGNUM_HAL_INTERRUPT_EINT3 &&
                vector >= CYGNUM_HAL_INTERRUPT_EINT0 , "Invalid vector");
 
@@ -390,7 +426,7 @@ void hal_lpc_watchdog_reset(void)
     // feed WD with the two magic values
     HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_WD_BASE + 
                      CYGARC_HAL_LPC24XX_REG_WDFEED, 
-                     CYGARC_HAL_LPC24XX_REG_WDFEED_MAGIC1);	
+                     CYGARC_HAL_LPC24XX_REG_WDFEED_MAGIC1); 
     HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_WD_BASE + 
                      CYGARC_HAL_LPC24XX_REG_WDFEED, 
                      CYGARC_HAL_LPC24XX_REG_WDFEED_MAGIC2);
@@ -399,5 +435,6 @@ void hal_lpc_watchdog_reset(void)
       continue;
 }
 
+
 //--------------------------------------------------------------------------
 // EOF lpc24xx_misc.c