File indexing completed on 2025-05-11 08:23:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <rtems/status-checks.h>
0023 #include <bsp.h>
0024 #include <bsp/io.h>
0025 #include <bsp/start.h>
0026 #include <bsp/system-clocks.h>
0027
0028
0029
0030
0031 static const lpc176x_module_entry lpc176x_module_table[] = {
0032 LPC176X_MODULE_ENTRY( LPC176X_MODULE_WD, 0, 1, 0 ),
0033 LPC176X_MODULE_ENTRY( LPC176X_MODULE_ADC, 1, 1, 12 ),
0034 LPC176X_MODULE_ENTRY( LPC176X_MODULE_CAN_0, 1, 1, 13 ),
0035 LPC176X_MODULE_ENTRY( LPC176X_MODULE_CAN_1, 1, 1, 14 ),
0036 LPC176X_MODULE_ENTRY(LPC176X_MODULE_ACCF, 0, 1, 15),
0037 LPC176X_MODULE_ENTRY( LPC176X_MODULE_DAC, 0, 1, 11 ),
0038 LPC176X_MODULE_ENTRY( LPC176X_MODULE_GPDMA, 1, 1, 29 ),
0039 LPC176X_MODULE_ENTRY( LPC176X_MODULE_GPIO, 0, 1, 15 ),
0040 LPC176X_MODULE_ENTRY( LPC176X_MODULE_I2S, 1, 1, 27 ),
0041 LPC176X_MODULE_ENTRY( LPC176X_MODULE_MCI, 1, 1, 28 ),
0042 LPC176X_MODULE_ENTRY( LPC176X_MODULE_MCPWM, 1, 1, 17 ),
0043 LPC176X_MODULE_ENTRY( LPC176X_MODULE_PCB, 0, 1, 18 ),
0044 LPC176X_MODULE_ENTRY( LPC176X_MODULE_PWM_0, 1, 1, 5 ),
0045 LPC176X_MODULE_ENTRY( LPC176X_MODULE_PWM_1, 1, 1, 6 ),
0046 LPC176X_MODULE_ENTRY( LPC176X_MODULE_QEI, 1, 1, 18 ),
0047 LPC176X_MODULE_ENTRY( LPC176X_MODULE_RTC, 1, 1, 9 ),
0048 LPC176X_MODULE_ENTRY( LPC176X_MODULE_SYSCON, 0, 1, 30 ),
0049 LPC176X_MODULE_ENTRY( LPC176X_MODULE_TIMER_0, 1, 1, 1 ),
0050 LPC176X_MODULE_ENTRY( LPC176X_MODULE_TIMER_1, 1, 1, 2 ),
0051 LPC176X_MODULE_ENTRY( LPC176X_MODULE_TIMER_2, 1, 1, 22 ),
0052 LPC176X_MODULE_ENTRY( LPC176X_MODULE_TIMER_3, 1, 1, 23 ),
0053 LPC176X_MODULE_ENTRY( LPC176X_MODULE_UART_0, 1, 1, 3 ),
0054 LPC176X_MODULE_ENTRY( LPC176X_MODULE_UART_1, 1, 1, 4 ),
0055 LPC176X_MODULE_ENTRY( LPC176X_MODULE_UART_2, 1, 1, 24 ),
0056 LPC176X_MODULE_ENTRY( LPC176X_MODULE_UART_3, 1, 1, 25 ),
0057 LPC176X_MODULE_ENTRY( LPC176X_MODULE_USB, 1, 0, 31 )
0058 };
0059
0060 inline void lpc176x_pin_select(
0061 const uint32_t pin,
0062 const lpc176x_pin_function function
0063 )
0064 {
0065 assert( pin <= LPC176X_IO_INDEX_MAX
0066 && function < LPC176X_PIN_FUNCTION_COUNT );
0067 const uint32_t pin_selected = LPC176X_PIN_SELECT( pin );
0068 volatile uint32_t *const pinsel = &LPC176X_PINSEL[ pin_selected ];
0069 const uint32_t shift = LPC176X_PIN_SELECT_SHIFT( pin );
0070 *pinsel = SET_FIELD( *pinsel, function,
0071 LPC176X_PIN_SELECT_MASK << shift, shift );
0072 }
0073
0074 void lpc176x_pin_set_mode(
0075 const uint32_t pin,
0076 const lpc176x_pin_mode mode
0077 )
0078 {
0079 assert( pin <= LPC176X_IO_INDEX_MAX
0080 && mode < LPC176X_PIN_MODE_COUNT );
0081 const uint32_t pin_selected = LPC176X_PIN_SELECT( pin );
0082 volatile uint32_t *const pinmode = &LPC176X_PINMODE[ pin_selected ];
0083 const uint32_t shift = LPC176X_PIN_SELECT_SHIFT( pin );
0084 *pinmode = SET_FIELD( *pinmode, mode,
0085 LPC176X_PIN_SELECT_MASK << shift, shift );
0086 }
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 static rtems_status_code check_power(
0097 const bool has_power,
0098 const unsigned index,
0099 const bool turn_on,
0100 rtems_interrupt_level level
0101 )
0102 {
0103 rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0104
0105 if ( index <= LPC176X_MODULE_BITS_COUNT ) {
0106 if ( has_power ) {
0107 rtems_interrupt_disable( level );
0108
0109 if ( turn_on ) {
0110 LPC176X_SCB.pconp |= 1u << index;
0111 } else {
0112 LPC176X_SCB.pconp &= ~( 1u << index );
0113 }
0114
0115 rtems_interrupt_enable( level );
0116 }
0117
0118
0119
0120
0121 status_code = RTEMS_SUCCESSFUL;
0122 }
0123
0124
0125
0126
0127 return status_code;
0128 }
0129
0130
0131
0132
0133
0134
0135
0136
0137 static inline void set_pclksel_value(
0138 const uint32_t pclksel,
0139 const lpc176x_module_clock clock,
0140 const unsigned clock_shift
0141 )
0142 {
0143 assert( pclksel < LPC176X_SCB_PCLKSEL_COUNT );
0144 const uint32_t setclock = ( clock << clock_shift );
0145 const uint32_t mask = ~( LPC176X_MODULE_CLOCK_MASK << clock_shift );
0146 LPC176X_SCB.pclksel[ pclksel ] = ( LPC176X_SCB.pclksel[ pclksel ] & mask ) |
0147 setclock;
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 static rtems_status_code check_clock(
0159 const bool has_clock,
0160 const unsigned index,
0161 const lpc176x_module_clock clock,
0162 rtems_interrupt_level level
0163 )
0164 {
0165 rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0166
0167 if ( index <= LPC176X_MODULE_BITS_COUNT ) {
0168 if ( has_clock ) {
0169 unsigned clock_shift = 2u * index;
0170 rtems_interrupt_disable( level );
0171
0172 if ( clock_shift < LPC176X_MODULE_BITS_COUNT ) {
0173
0174 set_pclksel_value( LPC176X_SCB_PCLKSEL0, clock, clock_shift );
0175 } else {
0176
0177 clock_shift -= LPC176X_MODULE_BITS_COUNT;
0178 set_pclksel_value( LPC176X_SCB_PCLKSEL1, clock, clock_shift );
0179 }
0180
0181 rtems_interrupt_enable( level );
0182 }
0183
0184
0185
0186
0187 status_code = RTEMS_SUCCESSFUL;
0188 }
0189
0190
0191
0192
0193 return status_code;
0194 }
0195
0196
0197
0198
0199
0200
0201 static rtems_status_code check_usb_module( void )
0202 {
0203 rtems_status_code status_code = RTEMS_INCORRECT_STATE;
0204 const uint32_t pllclk = lpc176x_pllclk();
0205 const uint32_t usbclk = LPC176X_USB_CLOCK;
0206
0207 if ( pllclk % usbclk == 0u ) {
0208 const uint32_t usbdiv = pllclk / usbclk;
0209
0210 LPC176X_SCB.usbclksel = LPC176X_SCB_USBCLKSEL_USBDIV( usbdiv ) |
0211 LPC176X_SCB_USBCLKSEL_USBSEL( 1 );
0212 status_code = RTEMS_SUCCESSFUL;
0213 }
0214
0215
0216
0217
0218 return status_code;
0219 }
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 static rtems_status_code enable_disable_module(
0230 const lpc176x_module module,
0231 const lpc176x_module_clock clock,
0232 const bool enable
0233 )
0234 {
0235 rtems_status_code status_code;
0236 rtems_interrupt_level level = 0u;
0237
0238 const bool has_power = lpc176x_module_table[ module ].power;
0239 const bool has_clock = lpc176x_module_table[ module ].clock;
0240 const unsigned index = lpc176x_module_table[ module ].index;
0241
0242 assert( index <= LPC176X_MODULE_BITS_COUNT );
0243
0244
0245 if ( enable ) {
0246 status_code = check_power( has_power, index, true, level );
0247 RTEMS_CHECK_SC( status_code,
0248 "Checking index shift to turn on power of the module." );
0249
0250 if ( module != LPC176X_MODULE_USB ) {
0251 status_code = check_clock( has_clock, index, clock, level );
0252 RTEMS_CHECK_SC( status_code,
0253 "Checking index shift to set pclksel to the current module." );
0254 } else {
0255 status_code = check_usb_module();
0256 RTEMS_CHECK_SC( status_code,
0257 "Checking pll clock to set usb clock to the current module." );
0258 }
0259 } else {
0260 status_code = check_power( has_power, index, false, level );
0261 RTEMS_CHECK_SC( status_code,
0262 "Checking index shift to turn off power of the module." );
0263 }
0264
0265 return status_code;
0266 }
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276 static rtems_status_code lpc176x_module_do_enable(
0277 const lpc176x_module module,
0278 lpc176x_module_clock clock,
0279 const bool enable
0280 )
0281 {
0282 rtems_status_code status_code = RTEMS_SUCCESSFUL;
0283
0284 if ( (unsigned) module >= LPC176X_MODULE_COUNT ) {
0285 return RTEMS_INVALID_ID;
0286 }
0287
0288
0289
0290
0291 if ( clock == LPC176X_MODULE_PCLK_DEFAULT ) {
0292 #if ( LPC176X_PCLKDIV == 1u )
0293 clock = LPC176X_MODULE_CCLK;
0294 #elif ( LPC176X_PCLKDIV == 2u )
0295 clock = LPC176X_MODULE_CCLK_2;
0296 #elif ( LPC176X_PCLKDIV == 4u )
0297 clock = LPC176X_MODULE_CCLK_4;
0298 #elif ( LPC176X_PCLKDIV == 8u )
0299 clock = LPC176X_MODULE_CCLK_8;
0300 #else
0301 #error "Unexpected clock divisor."
0302 #endif
0303 }
0304
0305
0306
0307 if ( ( clock & ~LPC176X_MODULE_CLOCK_MASK ) == 0u ) {
0308 status_code = enable_disable_module( module, clock, enable );
0309 RTEMS_CHECK_SC( status_code, "Checking the module to enable/disable." );
0310 } else {
0311 status_code = RTEMS_INVALID_CLOCK;
0312 }
0313
0314 return status_code;
0315 }
0316
0317 inline rtems_status_code lpc176x_module_enable(
0318 const lpc176x_module module,
0319 lpc176x_module_clock clock
0320 )
0321 {
0322 return lpc176x_module_do_enable( module, clock, true );
0323 }
0324
0325 inline rtems_status_code lpc176x_module_disable( const lpc176x_module module )
0326 {
0327 return lpc176x_module_do_enable( module,
0328 LPC176X_MODULE_PCLK_DEFAULT,
0329 false );
0330 }
0331
0332 bool lpc176x_module_is_enabled( const lpc176x_module module )
0333 {
0334 assert( (unsigned) module < LPC176X_MODULE_COUNT );
0335
0336 const bool has_power = lpc176x_module_table[ module ].power;
0337 bool enabled;
0338
0339 if ( has_power ) {
0340 const unsigned index = lpc176x_module_table[ module ].index;
0341 const uint32_t pconp = LPC176X_SCB.pconp;
0342
0343 enabled = ( pconp & ( 1u << index ) ) != 0u;
0344 } else {
0345 enabled = true;
0346 }
0347
0348 return enabled;
0349 }