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 <assert.h>
0023 #include <bsp/irq.h>
0024 #include <bsp/io.h>
0025 #include <bsp/lpc-gpio.h>
0026 #include <rtems/status-checks.h>
0027
0028 static uint32_t function_vector_size = 0u;
0029 static lpc176x_registered_interrupt_function function_vector[
0030 LPC176X_RESERVED_ISR_FUNCT_SIZE ];
0031 static bool isr_installed = false;
0032
0033 rtems_status_code lpc176x_gpio_config(
0034 const lpc176x_pin_number pin,
0035 const lpc176x_gpio_direction dir
0036 )
0037 {
0038 rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0039
0040 if ( ( pin < LPC176X_MAX_PORT_NUMBER ) &&
0041 ( dir < LPC176X_GPIO_FUNCTION_COUNT ) ) {
0042 const lpc176x_gpio_ports port = LPC176X_IO_PORT( pin );
0043 const uint32_t pin_of_port = LPC176X_IO_PORT_BIT( pin );
0044
0045 lpc176x_pin_select( pin, LPC176X_PIN_FUNCTION_00 );
0046
0047 LPC176X_SET_BIT( LPC176X_FIO[ port ].dir, pin_of_port, dir );
0048
0049 status_code = RTEMS_SUCCESSFUL;
0050 }
0051
0052
0053
0054
0055 return status_code;
0056 }
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 static bool lpc176x_check_rising_edge_and_call(
0067 const uint32_t statR,
0068 const lpc176x_registered_interrupt_function registered_isr_function,
0069 const uint32_t pin
0070 )
0071 {
0072 bool is_rising = false;
0073
0074 if ( statR & LPC176X_PIN_BIT( pin ) ) {
0075 registered_isr_function.function( registered_isr_function.pin,
0076 LPC176X_GPIO_INTERRUPT_RISING );
0077 is_rising = true;
0078 }
0079
0080
0081
0082
0083 return is_rising;
0084 }
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 static bool lpc176x_check_falling_edge_and_call(
0095 const uint32_t statF,
0096 const lpc176x_registered_interrupt_function registered_isr_function,
0097 const uint32_t pin
0098 )
0099 {
0100 bool is_falling = false;
0101
0102 if ( statF & LPC176X_PIN_BIT( pin ) ) {
0103 registered_isr_function.function( registered_isr_function.pin,
0104 LPC176X_GPIO_INTERRUPT_FALLING );
0105 is_falling = true;
0106 }
0107
0108
0109
0110
0111 return is_falling;
0112 }
0113
0114
0115
0116
0117
0118
0119
0120 static lpc176x_interrupt_control*lpc176x_get_interrupt_address(
0121 const lpc176x_gpio_ports port )
0122 {
0123 lpc176x_interrupt_control *interrupt;
0124
0125 switch ( port ) {
0126 case ( LPC176X_GPIO_PORT_0 ):
0127 interrupt = (lpc176x_interrupt_control *) LPC176X_IO0_INT_BASE_ADDRESS;
0128 break;
0129 case ( LPC176X_GPIO_PORT_2 ):
0130 interrupt = (lpc176x_interrupt_control *) LPC176X_IO2_INT_BASE_ADDRESS;
0131 break;
0132 case ( LPC176X_GPIO_PORT_1 ):
0133 case ( LPC176X_GPIO_PORT_3 ):
0134 case ( LPC176X_GPIO_PORT_4 ):
0135 default:
0136 interrupt = NULL;
0137 }
0138
0139 return interrupt;
0140 }
0141
0142
0143
0144
0145
0146
0147 static void check_for_interrupt(
0148 const lpc176x_registered_interrupt_function registered_isr_function )
0149 {
0150 assert( registered_isr_function.pin < LPC176X_MAX_PORT_NUMBER );
0151
0152 const lpc176x_gpio_ports port = LPC176X_IO_PORT(
0153 registered_isr_function.pin );
0154 const uint32_t pin = LPC176X_IO_PORT_BIT( registered_isr_function.pin );
0155
0156 lpc176x_interrupt_control *interrupt = lpc176x_get_interrupt_address( port );
0157 assert( interrupt != NULL );
0158
0159 bool is_rising_edge = lpc176x_check_rising_edge_and_call( interrupt->StatR,
0160 registered_isr_function,
0161 pin );
0162
0163 bool is_falling_edge = lpc176x_check_falling_edge_and_call( interrupt->StatF,
0164 registered_isr_function,
0165 pin );
0166
0167 if ( is_rising_edge || is_falling_edge ) {
0168 interrupt->Clr = LPC176X_PIN_BIT( pin );
0169 }
0170
0171
0172
0173 }
0174
0175
0176
0177
0178
0179
0180 static inline void lpc176x_gpio_isr( void *arg )
0181 {
0182 unsigned int i;
0183
0184 for ( i = 0; i < function_vector_size; ++i ) {
0185 check_for_interrupt( function_vector[ i ] );
0186 }
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196 static void lpc176x_set_falling_or_rising_interrupt(
0197 const lpc176x_gpio_interrupt edge,
0198 const uint32_t pin_of_port,
0199 lpc176x_interrupt_control *interrupt
0200 )
0201 {
0202 if ( edge & LPC176X_GPIO_INTERRUPT_RISING ) {
0203 LPC176X_SET_BIT( interrupt->EnR, pin_of_port, LPC176X_INT_ENABLE );
0204 }
0205
0206
0207
0208
0209 if ( edge & LPC176X_GPIO_INTERRUPT_FALLING ) {
0210 LPC176X_SET_BIT( interrupt->EnF, pin_of_port, LPC176X_INT_ENABLE );
0211 }
0212
0213
0214
0215 }
0216
0217
0218
0219
0220
0221
0222
0223
0224 static void lpc176x_register_pin_and_callback(
0225 const lpc176x_gpio_interrupt edge,
0226 const lpc176x_pin_number pin,
0227 const lpc176x_gpio_interrupt_function isr_funct
0228 )
0229 {
0230 if ( edge ) {
0231 assert( function_vector_size < LPC176X_RESERVED_ISR_FUNCT_SIZE );
0232 function_vector[ function_vector_size ].function = isr_funct;
0233 function_vector[ function_vector_size ].pin = pin;
0234 ++function_vector_size;
0235 }
0236
0237
0238
0239 }
0240
0241
0242
0243
0244
0245
0246
0247 static rtems_status_code lpc176x_install_interrupt_handler(
0248 const lpc176x_gpio_interrupt edge )
0249 {
0250 rtems_status_code status_code = RTEMS_SUCCESSFUL;
0251
0252 if ( !isr_installed && edge ) {
0253 status_code = rtems_interrupt_handler_install( LPC176X_IRQ_EINT_3,
0254 "gpio_interrupt",
0255 RTEMS_INTERRUPT_UNIQUE,
0256 lpc176x_gpio_isr,
0257 NULL );
0258 isr_installed = true;
0259 }
0260
0261
0262
0263
0264 return status_code;
0265 }
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 static rtems_status_code lpc176x_check_edge_and_set_gpio_interrupts(
0278 const lpc176x_pin_number pin,
0279 const lpc176x_gpio_interrupt edge,
0280 const lpc176x_gpio_interrupt_function isr_funct
0281 )
0282 {
0283 rtems_status_code status_code = RTEMS_SUCCESSFUL;
0284
0285 const lpc176x_gpio_ports port = LPC176X_IO_PORT( pin );
0286 const uint32_t pin_of_port = LPC176X_IO_PORT_BIT( pin );
0287
0288 lpc176x_interrupt_control *interrupt = lpc176x_get_interrupt_address( port );
0289
0290 assert( interrupt != NULL );
0291
0292 lpc176x_gpio_config( pin, LPC176X_GPIO_FUNCTION_INPUT );
0293
0294 lpc176x_set_falling_or_rising_interrupt( edge, pin_of_port, interrupt );
0295
0296 lpc176x_register_pin_and_callback( edge, pin, isr_funct );
0297
0298 status_code = lpc176x_install_interrupt_handler( edge );
0299
0300 return status_code;
0301 }
0302
0303 rtems_status_code lpc176x_gpio_config_input_with_interrupt(
0304 const lpc176x_pin_number pin,
0305 const lpc176x_gpio_interrupt edge,
0306 const lpc176x_gpio_interrupt_function isr_funct
0307 )
0308 {
0309 rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0310
0311 if ( ( pin < LPC176X_MAX_PORT_NUMBER )
0312 && ( edge < LPC176X_GPIO_INTERRUPT_COUNT ) ) {
0313 status_code = lpc176x_check_edge_and_set_gpio_interrupts( pin,
0314 edge,
0315 isr_funct );
0316 }
0317
0318
0319
0320
0321 return status_code;
0322 }
0323
0324 rtems_status_code lpc176x_gpio_set_pin( const lpc176x_pin_number pin )
0325 {
0326 rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0327
0328 if ( pin < LPC176X_MAX_PORT_NUMBER ) {
0329 const lpc176x_gpio_ports port = LPC176X_IO_PORT( pin );
0330 const uint32_t pin_of_port = LPC176X_IO_PORT_BIT( pin );
0331
0332 LPC176X_FIO[ port ].set = LPC176X_PIN_BIT( pin_of_port );
0333
0334 status_code = RTEMS_SUCCESSFUL;
0335 }
0336
0337
0338
0339
0340 return status_code;
0341 }
0342
0343 rtems_status_code lpc176x_gpio_clear_pin( const lpc176x_pin_number pin )
0344 {
0345 rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0346
0347 if ( pin < LPC176X_MAX_PORT_NUMBER ) {
0348 const lpc176x_gpio_ports port = LPC176X_IO_PORT( pin );
0349 const uint32_t pin_of_port = LPC176X_IO_PORT_BIT( pin );
0350
0351 LPC176X_FIO[ port ].clr = LPC176X_PIN_BIT( pin_of_port );
0352
0353 status_code = RTEMS_SUCCESSFUL;
0354 }
0355
0356
0357
0358
0359 return status_code;
0360 }
0361
0362 rtems_status_code lpc176x_gpio_write_pin(
0363 const lpc176x_pin_number pin,
0364 const bool value
0365 )
0366 {
0367 rtems_status_code status_code;
0368
0369 if ( value ) {
0370 status_code = lpc176x_gpio_set_pin( pin );
0371 } else {
0372 status_code = lpc176x_gpio_clear_pin( pin );
0373 }
0374
0375 return status_code;
0376 }
0377
0378 inline rtems_status_code lpc176x_gpio_get_pin_value(
0379 const lpc176x_pin_number pin,
0380 bool *pin_value
0381 )
0382 {
0383 assert( pin < LPC176X_MAX_PORT_NUMBER );
0384
0385 rtems_status_code status_code = RTEMS_SUCCESSFUL;
0386
0387 const lpc176x_gpio_ports port = LPC176X_IO_PORT( pin );
0388 const uint32_t pin_of_port = LPC176X_IO_PORT_BIT( pin );
0389 *pin_value = ( LPC176X_FIO[ port ].pin & LPC176X_PIN_BIT( pin_of_port ) );
0390
0391 return status_code;
0392 }