Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:03

0001 /**
0002  * @file
0003  *
0004  * @ingroup RTEMSBSPsARMLPC176X
0005  *
0006  * @brief First configurations and initializations to the correct
0007  *              functionality of the board.
0008  */
0009 
0010 /*
0011  * Copyright (c) 2014 Taller Technologies.
0012  *
0013  * @author  Boretto Martin    (martin.boretto@tallertechnologies.com)
0014  * @author  Diaz Marcos (marcos.diaz@tallertechnologies.com)
0015  * @author  Lenarduzzi Federico  (federico.lenarduzzi@tallertechnologies.com)
0016  * @author  Daniel Chicco  (daniel.chicco@tallertechnologies.com)
0017  *
0018  * The license and distribution terms for this file may be
0019  * found in the file LICENSE in this distribution or at
0020  * http://www.rtems.org/license/LICENSE.
0021  */
0022 
0023 #include <bsp.h>
0024 #include <bsp/start.h>
0025 #include <bsp/io.h>
0026 
0027 /**
0028  * @brief Initializes the oscillator according to the lpc176x board.
0029  */
0030 static BSP_START_TEXT_SECTION void lpc176x_init_main_oscillator( void )
0031 {
0032   if ( ( LPC176X_SCB.scs & LPC176X_SCB_SCS_OSC_STATUS ) == 0u ) {
0033     LPC176X_SCB.scs |= LPC176X_SCB_SCS_OSC_ENABLE;
0034 
0035     while ( ( LPC176X_SCB.scs & LPC176X_SCB_SCS_OSC_STATUS ) == 0u ) {
0036       /* Wait. */
0037     }
0038   }
0039 
0040   /* else implies that the oscillator is initialized. Also,
0041      there is nothing to do. */
0042 }
0043 
0044 /**
0045  * @brief Sets the PLL configuration.
0046  *
0047  * @param pll Value to set.
0048  * @param val Set value.
0049  */
0050 static BSP_START_TEXT_SECTION void lpc176x_pll_config( const uint32_t val )
0051 {
0052   ( LPC176X_SCB.pll_0 ).con = val;
0053   /* The two register writes must be in correct sequence. */
0054   ( LPC176X_SCB.pll_0 ).feed = LPC176X_PLL0CON;
0055   ( LPC176X_SCB.pll_0 ).feed = LPC176X_PLL0CFG;
0056 }
0057 
0058 /**
0059  * @brief Sets the PLL.
0060  *
0061  * @param msel Multiplier value.
0062  * @param psel Divider value.
0063  * @param cclkdiv Divisor clock.
0064  */
0065 static BSP_START_TEXT_SECTION void lpc176x_set_pll(
0066   const unsigned msel,
0067   const unsigned psel,
0068   const unsigned cclkdiv
0069 )
0070 {
0071   const uint32_t pllcfg = LPC176X_PLL_SEL_MSEL( msel ) |
0072                           LPC176X_PLL_SEL_PSEL( psel );
0073   const uint32_t pllstat = LPC176X_PLL_STAT_PLLE | LPC176X_PLL_STAT_PLOCK |
0074                            pllcfg;
0075   const uint32_t cclksel_cclkdiv = LPC176X_SCB_CCLKSEL_CCLKDIV( cclkdiv );
0076 
0077   if ( ( LPC176X_SCB.pll_0 ).stat != pllstat
0078        || LPC176X_SCB.cclksel != cclksel_cclkdiv
0079        || LPC176X_SCB.clksrcsel != LPC176X_SCB_CLKSRCSEL_CLKSRC ) {
0080     lpc176x_pll_config( ( LPC176X_SCB.pll_0 ).con & ~LPC176X_PLL_CON_PLLC );
0081 
0082     /* Turn off USB.  */
0083     LPC176X_SCB.usbclksel = 0u;
0084 
0085     /* Disable PLL. */
0086     lpc176x_pll_config( 0u );
0087 
0088     /* Use SYSCLK for CCLK. */
0089     LPC176X_SCB.cclksel = LPC176X_SCB_CCLKSEL_CCLKDIV( 0u );
0090 
0091     /* Set the CCLK, PCLK and EMCCLK divider. */
0092     LPC176X_SCB.cclksel = cclksel_cclkdiv;
0093 
0094     /* Select main oscillator as clock source. */
0095     LPC176X_SCB.clksrcsel = LPC176X_SCB_CLKSRCSEL_CLKSRC;
0096 
0097     /* The two register writes must be in correct sequence. */
0098     /* Set PLL configuration. */
0099     ( LPC176X_SCB.pll_0 ).cfg = pllcfg;
0100     ( LPC176X_SCB.pll_0 ).feed = LPC176X_PLL0CON;
0101     ( LPC176X_SCB.pll_0 ).feed = LPC176X_PLL0CFG;
0102 
0103     /* Enable PLL. */
0104     lpc176x_pll_config( LPC176X_PLL_CON_PLLE );
0105 
0106     /* Wait for lock. */
0107     while ( ( ( LPC176X_SCB.pll_0 ).stat & LPC176X_PLL_STAT_PLOCK ) == 0u ) {
0108       /* Wait */
0109     }
0110 
0111     /* Connect PLL. */
0112     lpc176x_pll_config( ( LPC176X_PLL_CON_PLLE | LPC176X_PLL_CON_PLLC ) );
0113 
0114     /* Wait for connected and enabled. */
0115     while ( ( ( LPC176X_SCB.pll_0 ).stat & ( LPC176X_PLL_STAT_PLLE |
0116                                              LPC176X_PLL_STAT_PLLC ) ) ==
0117             0u ) {
0118       /* Wait  */
0119     }
0120   }
0121 
0122   /* else implies that the pll has a wrong value. Also,
0123      there is nothing to do. */
0124 }
0125 
0126 /**
0127  * @brief Pll initialization.
0128  */
0129 static BSP_START_TEXT_SECTION void lpc176x_init_pll( void )
0130 {
0131 #if ( LPC176X_OSCILLATOR_MAIN == 12000000u )
0132 #if ( LPC176X_CCLK == 96000000U )
0133   lpc176x_set_pll( 11u, 0u, 2u );
0134 #else
0135 #error "unexpected CCLK"
0136 #endif
0137 #else
0138 #error "unexpected main oscillator frequency"
0139 #endif
0140 }
0141 
0142 /**
0143  * @brief Memory map initialization.
0144  */
0145 static BSP_START_TEXT_SECTION void lpc176x_init_memory_map( void )
0146 {
0147   LPC176X_SCB.memmap = LPC176X_SCB_MEMMAP_MAP;
0148 }
0149 
0150 /**
0151  * @brief Memory accelerator initialization.
0152  */
0153 static BSP_START_TEXT_SECTION void lpc176x_init_memory_accelerator( void )
0154 {
0155 #if ( LPC176X_CCLK <= 20000000U )
0156   LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x0U );
0157 #elif ( LPC176X_CCLK <= 40000000U )
0158   LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x1U );
0159 #elif ( LPC176X_CCLK <= 60000000U )
0160   LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x2U );
0161 #elif ( LPC176X_CCLK <= 80000000U )
0162   LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x3U );
0163 #elif ( LPC176X_CCLK <= 100000000U )
0164   LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x4U );
0165 #else
0166   LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x5U );
0167 #endif
0168 }
0169 
0170 /**
0171  * @brief Stops the gpdma device.
0172  */
0173 static BSP_START_TEXT_SECTION void lpc176x_stop_gpdma( void )
0174 {
0175 #ifdef LPC176X_STOP_GPDMA
0176 
0177   bool has_power = ( LPC176X_SCB.pconp & LPC176X_SCB_PCONP_GPDMA ) != 0u;
0178 
0179   if ( has_power ) {
0180     GPDMA_CONFIG = 0u;
0181     LPC176X_SCB.pconp &= ~LPC176X_SCB_PCONP_GPDMA;
0182   }
0183 
0184   /* else implies that the current module (gpdma) is turn off. Also,
0185      there is nothing to do. */
0186 
0187 #endif
0188 }
0189 
0190 /**
0191  * @brief Stops the usb device.
0192  */
0193 static BSP_START_TEXT_SECTION void lpc176x_stop_usb( void )
0194 {
0195 #ifdef LPC176X_STOP_USB
0196 
0197   bool has_power = ( LPC176X_SCB.pconp & LPC176X_SCB_PCONP_USB ) != 0u;
0198 
0199   if ( has_power ) {
0200     OTG_CLK_CTRL = 0u;
0201 
0202     LPC176X_SCB.pconp &= ~LPC176X_SCB_PCONP_USB;
0203     LPC176X_SCB.usbclksel = 0u;
0204   }
0205 
0206   /* else implies that the current module (usb) is turn off. Also,
0207      there is nothing to do. */
0208 #endif
0209 }
0210 
0211 BSP_START_TEXT_SECTION void bsp_start_hook_0( void )
0212 {
0213   lpc176x_init_main_oscillator();
0214   lpc176x_init_pll();
0215 }
0216 
0217 BSP_START_TEXT_SECTION void bsp_start_hook_1( void )
0218 {
0219   lpc176x_init_memory_map();
0220   lpc176x_init_memory_accelerator();
0221   lpc176x_stop_gpdma();
0222   lpc176x_stop_usb();
0223   bsp_start_copy_sections();
0224   bsp_start_clear_bss();
0225 
0226   /* At this point we can use objects outside the .start section  */
0227 }