This patch adds support for the following devices to the LPC176x BSP: * CAN * PWM * ADC
It also adds the probe routines for UART1/2/3 to the console_device_table in console-config.c, and enables UART1 in configure.ac. --- c/src/lib/libbsp/arm/lpc176x/Makefile.am | 16 + c/src/lib/libbsp/arm/lpc176x/adc/adc.c | 244 ++++++++++ c/src/lib/libbsp/arm/lpc176x/can/can.c | 542 +++++++++++++++++++++ c/src/lib/libbsp/arm/lpc176x/configure.ac | 3 + .../libbsp/arm/lpc176x/console/console-config.c | 42 +- c/src/lib/libbsp/arm/lpc176x/include/adc-defs.h | 96 ++++ c/src/lib/libbsp/arm/lpc176x/include/adc.h | 60 +++ c/src/lib/libbsp/arm/lpc176x/include/can-defs.h | 183 +++++++ c/src/lib/libbsp/arm/lpc176x/include/can.h | 179 +++++++ .../lib/libbsp/arm/lpc176x/include/common-types.h | 1 + c/src/lib/libbsp/arm/lpc176x/include/io-defs.h | 19 + c/src/lib/libbsp/arm/lpc176x/include/io.h | 13 +- c/src/lib/libbsp/arm/lpc176x/include/lpc176x.h | 8 +- c/src/lib/libbsp/arm/lpc176x/include/mbed-pinmap.h | 50 ++ c/src/lib/libbsp/arm/lpc176x/include/pwmout-defs.h | 105 ++++ c/src/lib/libbsp/arm/lpc176x/include/pwmout.h | 73 +++ c/src/lib/libbsp/arm/lpc176x/misc/io.c | 15 + c/src/lib/libbsp/arm/lpc176x/preinstall.am | 28 ++ c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c | 210 ++++++++ c/src/lib/libbsp/shared/include/uart-output-char.h | 4 +- 20 files changed, 1881 insertions(+), 10 deletions(-) create mode 100755 c/src/lib/libbsp/arm/lpc176x/adc/adc.c create mode 100755 c/src/lib/libbsp/arm/lpc176x/can/can.c create mode 100755 c/src/lib/libbsp/arm/lpc176x/include/adc-defs.h create mode 100755 c/src/lib/libbsp/arm/lpc176x/include/adc.h create mode 100755 c/src/lib/libbsp/arm/lpc176x/include/can-defs.h create mode 100755 c/src/lib/libbsp/arm/lpc176x/include/can.h create mode 100755 c/src/lib/libbsp/arm/lpc176x/include/mbed-pinmap.h create mode 100755 c/src/lib/libbsp/arm/lpc176x/include/pwmout-defs.h create mode 100755 c/src/lib/libbsp/arm/lpc176x/include/pwmout.h create mode 100755 c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c diff --git a/c/src/lib/libbsp/arm/lpc176x/Makefile.am b/c/src/lib/libbsp/arm/lpc176x/Makefile.am index 3f60f23..50a7e79 100644 --- a/c/src/lib/libbsp/arm/lpc176x/Makefile.am +++ b/c/src/lib/libbsp/arm/lpc176x/Makefile.am @@ -42,6 +42,12 @@ include_bsp_HEADERS += include/io.h include_bsp_HEADERS += include/common-types.h include_bsp_HEADERS += include/gpio-defs.h include_bsp_HEADERS += include/gpio.h +include_bsp_HEADERS += include/can.h +include_bsp_HEADERS += include/can-defs.h +include_bsp_HEADERS += include/pwmout.h +include_bsp_HEADERS += include/pwmout-defs.h +include_bsp_HEADERS += include/adc.h +include_bsp_HEADERS += include/adc-defs.h include_bsp_HEADERS += include/timer-defs.h include_bsp_HEADERS += include/timer.h include_bsp_HEADERS += include/watchdog.h @@ -50,6 +56,7 @@ include_bsp_HEADERS += include/irq.h include_bsp_HEADERS += include/lpc176x.h include_bsp_HEADERS += include/lpc-clock-config.h include_bsp_HEADERS += include/system-clocks.h +include_bsp_HEADERS += include/mbed-pinmap.h include_HEADERS += ../../shared/include/tm27.h @@ -126,6 +133,15 @@ libbsp_a_SOURCES += ../../shared/tod.c \ # GPIO libbsp_a_SOURCES += gpio/gpio.c +# CAN +libbsp_a_SOURCES += can/can.c + +# PWMOUT +libbsp_a_SOURCES += pwmout/pwmout.c + +# ADC +libbsp_a_SOURCES += adc/adc.c + # Timer libbsp_a_SOURCES += timer/timer.c diff --git a/c/src/lib/libbsp/arm/lpc176x/adc/adc.c b/c/src/lib/libbsp/arm/lpc176x/adc/adc.c new file mode 100755 index 0000000..7cf003a --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc176x/adc/adc.c @@ -0,0 +1,244 @@ +/** + * @file adc.c + * + * @ingroup lpc176x + * + * @brief ADC library for the lpc176x bsp. + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Diaz Marcos (marcos.d...@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ +#include <rtems/status-checks.h> +#include <bsp/adc.h> +#include <bsp/adc-defs.h> + +static lpc176x_adc_device *const adc_device = AD0_BASE_ADDR; + +static const lpc176x_adc_pin_map adc_pinmap[ ADC_DEVICES_COUNT ] = +{ + { + .pin_number = 23u, + .pin_function = LPC176X_PIN_FUNCTION_01 + }, + { + .pin_number = 24u, + .pin_function = LPC176X_PIN_FUNCTION_01 + }, + { + .pin_number = 25u, + .pin_function = LPC176X_PIN_FUNCTION_01 + }, + { + .pin_number = 26u, + .pin_function = LPC176X_PIN_FUNCTION_01 + }, + { + .pin_number = 62u, + .pin_function = LPC176X_PIN_FUNCTION_11 + }, + { + .pin_number = 63u, + .pin_function = LPC176X_PIN_FUNCTION_11 + }, + { + .pin_number = 3u, + .pin_function = LPC176X_PIN_FUNCTION_10 + }, + { + .pin_number = 2u, + .pin_function = LPC176X_PIN_FUNCTION_10 + } +}; + +/** + * @brief Checks for a valid pin number for an ADC + * + * @param pin_number The pin to check + * @param adc_number The returned ADC device corresponding to that pin. + * + * @return true if valid, false otherwise. + */ +static bool valid_pin_number ( + const lpc176x_pin_number pin_number, + lpc176x_adc_number *const adc_number + ) +{ + bool found = false; + lpc176x_adc_number adc_device = ADC_0; + + while (!found && (adc_device < ADC_DEVICES_COUNT)) + { + if (adc_pinmap[adc_device].pin_number == pin_number) + { + *adc_number = adc_device; + found = true; + } + ++adc_device; + } + + return found; +} + +/** + * @brief Turns on the device and sets its clock divisor. + * + */ +static void turn_on_and_set_clkdiv( void ) +{ + const uint32_t clkdiv = LPC176X_CCLK / ( LPC176X_PCLKDIV * MAX_ADC_CLK ); + + adc_device->ADCR = ADC_CR_PDN | ADC_CR_CLKDIV( clkdiv ); +} + +rtems_status_code adc_open( const lpc176x_pin_number pin_number ) +{ + rtems_status_code sc = RTEMS_INVALID_NUMBER; + lpc176x_adc_number adc_number = 0; + if ( valid_pin_number( pin_number, &adc_number ) ) { + sc = + lpc176x_module_enable( LPC176X_MODULE_ADC, LPC176X_MODULE_PCLK_DEFAULT ); + RTEMS_CHECK_SC( sc, "enable adc module" ); + + turn_on_and_set_clkdiv(); + lpc176x_pin_select( adc_pinmap[ adc_number ].pin_number, + adc_pinmap[ adc_number ].pin_function ); + lpc176x_pin_set_mode( adc_pinmap[ adc_number ].pin_number, + LPC176X_PIN_MODE_NONE ); + } + + return sc; +} + +rtems_status_code adc_close( void ) +{ + adc_device->ADCR &= ~ADC_CR_PDN; + + return lpc176x_module_disable( LPC176X_MODULE_ADC ); +} + +/** + * @brief Starts the conversion for the given channel. + * + * @param number The channel to start the conversion. + */ +static inline void start_conversion( const lpc176x_adc_number number ) +{ + adc_device->ADCR = + ADC_CR_SEL_SET( adc_device->ADCR, ( 1 << number ) ) | ADC_CR_START_NOW; +} + +/** + * @brief Stops the conversion. + * + */ +static inline void stop_conversion( void ) +{ + adc_device->ADCR &= ~ADC_CR_START_NOW; +} + +/** + * @brief Gets float percentage of the result of a conversion. + * + * @param data The result of a conversion. + * @return A float percentage (between 0.0f and 1.0f). + */ +static inline float get_float( const uint32_t data ) +{ + return ( (float) data / (float) ADC_RANGE ); +} + + +/** + * @brief Reads the ADC value for the given ADC number. + * + * @param adc_number Which ADC device read. + * @return The read value. + */ +static uint32_t read( const lpc176x_adc_number adc_number ) +{ + uint32_t data; + + start_conversion( adc_number ); + + do { + data = adc_device->ADGDR; + } while ( !ADC_DATA_CONVERSION_DONE( data ) ); + + stop_conversion(); + + return ADC_DR_VALUE( data ); +} + +/** + * @brief Checks if the passed parameters are ordered from lowest + * to highest. + * + * @param a The suggested lowest value. + * @param b The suggested middle value. + * @param c The suggested highest value. + * @return True if it is in the right order, false otherwise. + */ +static inline bool lowest_to_highest_ordered( + const uint32_t a, + const uint32_t b, + const uint32_t c +) +{ + return ( ( a <= b ) && ( b <= c ) ); +} + +/** + * @brief Gets median value from the three passed parameters. + * + * @param a The first parameter. + * @param b The second parameter. + * @param c The third parameter. + * + * @return The median of the three parameters. + */ +static uint32_t get_median( + const uint32_t a, + const uint32_t b, + const uint32_t c +) +{ + uint32_t median; + + if ( lowest_to_highest_ordered( a, b, c) + || lowest_to_highest_ordered( c, b, a ) ) { + median = b; + } else if ( lowest_to_highest_ordered( b, a, c ) + || lowest_to_highest_ordered( c, a, b ) ) { + median = a; + } else { + median = c; + } + + return median; +} + +rtems_status_code adc_read( + const lpc176x_pin_number pin_number , + float *const result +) +{ + rtems_status_code sc = RTEMS_INVALID_NUMBER; + lpc176x_adc_number adc_number = 0; + if ( valid_pin_number( pin_number, &adc_number ) ) { + const uint32_t first = read( adc_number ); + const uint32_t second = read( adc_number ); + const uint32_t third = read( adc_number ); + const uint32_t median = get_median( first, second, third ); + *result = get_float( median ); + sc = RTEMS_SUCCESSFUL; + } + + return sc; +} diff --git a/c/src/lib/libbsp/arm/lpc176x/can/can.c b/c/src/lib/libbsp/arm/lpc176x/can/can.c new file mode 100755 index 0000000..8bb20f4 --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc176x/can/can.c @@ -0,0 +1,542 @@ +/** + * @file can.c + * + * @ingroup lpc176x + * + * @brief CAN controller for the mbed lpc1768 board. + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Diaz Marcos (marcos.d...@tallertechnologies.com) + * @author Daniel Chicco (daniel.chi...@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include <rtems/status-checks.h> +#include <bsp/irq.h> +#include <bsp/can.h> +#include <bsp/can-defs.h> +#include <bsp/mbed-pinmap.h> + +/** + * @brief The standard isr to be installed for all the can devices. + * + * @param arg unused. + */ +static void can_isr( void *arg ); + +/** + * @brief Vector of isr for the can_driver . + */ +lpc176x_can_isr_vector isr_vector; + +/** + * @brief Represents all the can devices, and useful things for initialization. + */ +static const can_driver_entry can_driver_table[ CAN_DEVICES_NUMBER ] = +{ + { + .device = (can_device *) CAN1_BASE_ADDR, + .module = LPC176X_MODULE_CAN_0, + .pconp_pin = LPC176X_SCB_PCONP_CAN_1, + .pins = { DIP9, DIP10 }, + .pinfunction = LPC176X_PIN_FUNCTION_01 + }, + { + .device = (can_device *) CAN2_BASE_ADDR, + .module = LPC176X_MODULE_CAN_1, + .pconp_pin = LPC176X_SCB_PCONP_CAN_2, + .pins = { DIP30, DIP29 }, + .pinfunction = LPC176X_PIN_FUNCTION_10 + } +}; + +/** + * @brief The CAN acceptance filter. + */ +can_acceptance_filter *const acceptance_filter_device = + (can_acceptance_filter *) CAN_ACCEPT_BASE_ADDR; + +/** + * @brief Sets RX and TX pins for the passed can device number. + * + * @param cannumber CAN controller to be used. + */ +static inline void setpins( const lpc176x_can_number cannumber ) +{ + const can_driver_entry *const can_driver = &can_driver_table[ cannumber ]; + + lpc176x_pin_select( can_driver->pins[ CAN_TX_PIN ], + can_driver->pinfunction ); + lpc176x_pin_select( can_driver->pins[ CAN_RX_PIN ], + can_driver->pinfunction ); +} + +rtems_status_code can_close( const lpc176x_can_number minor ) +{ + rtems_status_code sc = RTEMS_INVALID_NUMBER; + + if ( CAN_DRIVER_IS_MINOR_VALID( minor ) ) { + sc = RTEMS_SUCCESSFUL; + const can_driver_entry *const can_driver = &can_driver_table[ minor ]; + lpc176x_module_disable( can_driver->module ); + } + + /*else wrong parameters. return RTEMS_INVALID_NUMBER*/ + + return sc; +} + +/** + * @brief Enables CAN device. + * + * @param obj The device to be enabled. + */ +static inline void can_enable( const can_driver_entry *const obj ) +{ + if ( obj->device->MOD & CAN_MOD_RM ) { + obj->device->MOD &= ~( CAN_MOD_RM ); + } +} + +/** + * @brief Disables CAN device to set parameters, and returns the previous value + * of the MOD register. + * + * @param obj The device to disable. + * @return The previous status of MOD register. + */ +static inline uint32_t can_disable( const can_driver_entry *const obj ) +{ + const uint32_t sm = obj->device->MOD; + + obj->device->MOD |= CAN_MOD_RM; + + return sm; +} + +/** + * @brief Resets the error count. + * + * @param obj which device reset. + */ +static inline void can_reset( const can_driver_entry *const obj ) +{ + can_disable( obj ); + obj->device->GSR = 0; /* Reset error counter when CANxMOD is in reset*/ +} + +/** + * @brief This table has the sampling points as close to 75% as possible. + * The first value is TSEG1, the second is TSEG2. + */ +static const unsigned int timing_pts[ MAX_TSEG1_TSEG2_BITS + + 1 ][ CAN_NUMBER_OF_TSEG ] = { + { 0x0, 0x0 }, /* 2, 50%*/ + { 0x1, 0x0 }, /* 3, 67%*/ + { 0x2, 0x0 }, /* 4, 75%*/ + { 0x3, 0x0 }, /* 5, 80%*/ + { 0x3, 0x1 }, /* 6, 67%*/ + { 0x4, 0x1 }, /* 7, 71%*/ + { 0x5, 0x1 }, /* 8, 75%*/ + { 0x6, 0x1 }, /* 9, 78%*/ + { 0x6, 0x2 }, /* 10, 70%*/ + { 0x7, 0x2 }, /* 11, 73%*/ + { 0x8, 0x2 }, /* 12, 75%*/ + { 0x9, 0x2 }, /* 13, 77%*/ + { 0x9, 0x3 }, /* 14, 71%*/ + { 0xA, 0x3 }, /* 15, 73%*/ + { 0xB, 0x3 }, /* 16, 75%*/ + { 0xC, 0x3 }, /* 17, 76%*/ + { 0xD, 0x3 }, /* 18, 78%*/ + { 0xD, 0x4 }, /* 19, 74%*/ + { 0xE, 0x4 }, /* 20, 75%*/ + { 0xF, 0x4 }, /* 21, 76%*/ + { 0xF, 0x5 }, /* 22, 73%*/ + { 0xF, 0x6 }, /* 23, 70%*/ + { 0xF, 0x7 }, /* 24, 67%*/ +}; + +/** + * @brief Checks if divisor is a divisor of value. + * + * @param value The number to be divided. + * @param divisor The divisor to check. + * + * @return true if "number" is divided by "divisor"; false otherwise. + */ +static inline bool is_divisor( + const uint32_t value, + const uint16_t divisor +) +{ + return ( ( value % divisor ) == 0 ); +} + +/** + * @brief Gets the size of the two tseg values added according to the given + * bitwidth and brp (The CAN prescaler). + * + * @param bitwidth The total bitwidth of a CAN bit (in pclk clocks). + * @param brp The CAN clock prescaler. + * + * @return The value of tseg1 + tseg2 of the CAN bit. It is useful + * to serve for index for timing_pts array). + */ +static inline uint32_t get_tseg_bit_size( + const uint32_t bitwidth, + const uint16_t brp +) +{ + return ( ( bitwidth / ( brp + CAN_BRP_EXTRA_BIT ) ) - CAN_TSEG_EXTRA_BITS ); +} + +/** + * @brief Gets the brp and tsegbitsize in order to achieve the desired bitwidth. + * @details The following must be fullfilled: + *(brp + CAN_BRP_EXTRA_BIT) * (tsegbitsize + CAN_TSEG_EXTRA_BITS) == bitwidth + * + * @param bitwidth The bitwidth that we need to achieve. + * @param brp Here it returns the calculated brp value. + * @param tsegbitsize Here it returns the calculated tseg bit size value. + * @return true if brp and tsegbitsize have been calculated. + */ +static inline bool get_brp_and_bitsize( + const uint32_t bitwidth, + uint16_t *const brp, + uint32_t *const tsegbitsize +) +{ + bool hit = false; + + while ( ( !hit ) && ( *brp < bitwidth / MIN_NUMBER_OF_CAN_BITS ) ) { + if ( ( is_divisor( bitwidth, *brp + CAN_BRP_EXTRA_BIT ) ) + && ( get_tseg_bit_size( bitwidth, *brp ) < MAX_TSEG1_TSEG2_BITS ) ) { + hit = true; + *tsegbitsize = get_tseg_bit_size( bitwidth, *brp ); + } else { /*Correct values not found, keep looking*/ + ( *brp )++; + } + } + + return hit; +} + +/** + * @brief Constructs the btr register with the passed arguments. + * + * @param tsegbitsize The size tseg bits to set. + * @param psjw The sjw to set. + * @param brp The prescaler value to set. + * @return The constructed btr register. + */ +static inline uint32_t get_btr( + const uint32_t tsegbitsize, + const unsigned char psjw, + const uint32_t brp +) +{ + const uint32_t tseg2_value_masked = + ( ( timing_pts[ tsegbitsize ][ CAN_TSEG2 ] << CAN_BTR_TSEG2_SHIFT ) & + CAN_BTR_TSEG2_MASK ); + const uint32_t tseg1_value_masked = + ( ( timing_pts[ tsegbitsize ][ CAN_TSEG1 ] << + CAN_BTR_TSEG1_SHIFT ) & CAN_BTR_TSEG1_MASK ); + const uint32_t psjw_value_masked = + ( ( psjw << CAN_BTR_SJW_SHIFT ) & CAN_BTR_SJW_MASK ); + const uint32_t brp_value_masked = + ( ( brp << CAN_BTR_BRP_SHIFT ) & CAN_BTR_BRP_MASK ); + + return tseg1_value_masked | tseg2_value_masked | + psjw_value_masked | brp_value_masked; +} + +/** + * @brief Calculates and returns a bit timing register (btr) for the desired + * canclk frequency using the passed psjw, system clock and peripheral clock. + * + * @param systemclk The clock of the system (in Hz). + * @param pclkdiv The peripheral clock divisor for the can device. + * @param canclk The desired frequency for CAN (in Hz). + * @param psjw The desired psjw. + * @return The btr register value if found, WRONG_BTR_VALUE otherwise. + */ +static inline unsigned int can_speed( + const unsigned int systemclk, + const unsigned int pclkdiv, + const unsigned int canclk, + const unsigned char psjw +) +{ + uint32_t btr = WRONG_BTR_VALUE; + const uint32_t bitwidth = systemclk / ( pclkdiv * canclk ); + + /* This is for the brp (prescaler) to start searching a reachable multiple.*/ + uint16_t brp = bitwidth / MAX_NUMBER_OF_CAN_BITS; + uint32_t tsegbitsize; + + if ( get_brp_and_bitsize( bitwidth, &brp, &tsegbitsize ) ) { + btr = get_btr( tsegbitsize, psjw, brp ); + } + + return btr; +} + +/** + * @brief Configures the desired CAN device with the desired frequency. + * + * @param obj The can device to configure. + * @param f The desired frequency. + * + * @return RTEMS_SUCCESSFUL if could be set, RTEMS_INVALID_NUMBER otherwise. + */ +static rtems_status_code can_frequency( + const can_driver_entry *const obj, + const can_freq freq +) +{ + rtems_status_code sc = RTEMS_INVALID_NUMBER; + const uint32_t btr = can_speed( LPC176X_CCLK, LPC176X_PCLKDIV, freq, 1 ); + + if ( btr != WRONG_BTR_VALUE ) { + sc = RTEMS_SUCCESSFUL; + uint32_t modmask = can_disable( obj ); + obj->device->BTR = btr; + obj->device->MOD = modmask; + } /*else couldnt found a good timing for the desired frequency, + return RTEMS_INVALID_NUMBER.*/ + + return sc; +} + +/** + * @brief Installs the interrupt handler in rtems. + */ +static inline rtems_status_code can_initialize( void ) +{ + return rtems_interrupt_handler_install( + LPC176X_IRQ_CAN, + "can_interrupt", + RTEMS_INTERRUPT_UNIQUE, + can_isr, + NULL + ); +} + +rtems_status_code can_open( const lpc176x_can_number minor, can_freq freq ) +{ + const can_driver_entry *const can_driver = &can_driver_table[ minor ]; + rtems_status_code sc = RTEMS_INVALID_NUMBER; + + if ( CAN_DRIVER_IS_MINOR_VALID( minor ) ) { + /*Enable CAN and acceptance filter modules.*/ + sc = + lpc176x_module_enable( can_driver->module, LPC176X_MODULE_PCLK_DEFAULT ); + RTEMS_CHECK_SC( sc, "enable can module" ); + sc = lpc176x_module_enable( LPC176X_MODULE_ACCF, + LPC176X_MODULE_PCLK_DEFAULT ); + RTEMS_CHECK_SC( sc, "enable acceptance filter" ); + /*Set pin functions.*/ + setpins( minor ); + + can_reset( can_driver ); + can_driver->device->IER = CAN_DEFAULT_INTERRUPT_CONFIGURATION; + sc = can_frequency( can_driver, freq ); + RTEMS_CHECK_SC( sc, "Configure CAN frequency" ); + can_initialize(); + + acceptance_filter_device->AFMR = CAN_ACCF_AFMR_ACCBP; /*Bypass Filter.*/ + } + + return sc; +} + +/** + * @brief Calls the installed isrs, according to the active interrupts. + * + * @param vector The read vector of active interrupts. + * @param number The CAN device to look for interruptions. + */ +static inline void call_isrs( + const uint32_t vector, + const lpc176x_can_number number +) +{ + can_irq_type i; + + for ( i = IRQ_RX; i < CAN_IRQ_NUMBER; ++i ) { + if ( ( isr_vector[ i ] != NULL ) && ( vector & ( 1 << i ) ) ) + isr_vector[ i ]( number ); + + /* else this interrupt has not been raised or it hasn't got a handler, + so do nothing.*/ + } +} + +/** + * @brief Checks if the passed CAN device is enabled and if it is checks for + * active interrupts and calls its installed isr. + * + * @param number The CAN device to check for interrupts rised. + */ +static inline void search_and_call_int( const lpc176x_can_number number ) +{ + const can_driver_entry *const driver = &can_driver_table[ number ]; + + if ( LPC176X_SCB.pconp & driver->pconp_pin ) { + /*We must read the whole register at once because it resets when read.*/ + const uint32_t int_vector = driver->device->ICR & CAN_INTERRUPT_TYPE_MASK; + call_isrs( int_vector, number ); + } + + /*else the device is shut down so we must do nothing.*/ +} + +/** + * @brief The standard isr to be installed for all the CAN devices. + * + * @param arg unused. + */ +static void can_isr( void *arg ) +{ + lpc176x_can_number i; + + for ( i = CAN_0; i < CAN_DEVICES_NUMBER; ++i ) { + search_and_call_int( i ); + } +} + +rtems_status_code can_read( + const lpc176x_can_number minor, + can_message *message +) +{ + rtems_status_code sc = RTEMS_IO_ERROR; + const can_driver_entry *const can_driver = &can_driver_table[ minor ]; + can_device *const dev = can_driver->device; + registers_can_message *const msg = &( message->registers ); + + can_enable( can_driver ); + + if ( dev->GSR & CAN_GSR_RBS_MASK ) { + sc = RTEMS_SUCCESSFUL; + *msg = dev->receive; + dev->CMR = CAN_CMR_RRB_MASK; /* release receive buffer. */ + } /* else Message not received.*/ + + return sc; +} + +/** + * @brief Array of masks and control bits for the transmit buffers. + * It's used for each transmit buffer in order to see if it's available and to + * send data to them. + */ +static const can_transmit_info transmit_info[ CAN_NUMBER_OF_TRANSMIT_BUFFERS ] + = + { + { + .can_status_mask = 0x00000004U, + .not_cc_cmr_value = 0x21U + }, + { + .can_status_mask = 0x00000400U, + .not_cc_cmr_value = 0x41U + }, + { + .can_status_mask = 0x00040000U, + .not_cc_cmr_value = 0x81U + } + }; + +rtems_status_code can_write( + const lpc176x_can_number minor, + const can_message *const message +) +{ + const can_driver_entry *const can_driver = &can_driver_table[ minor ]; + can_device *const obj = can_driver->device; + const uint32_t CANStatus = obj->SR; + + const registers_can_message *const msg = &( message->registers ); + rtems_status_code sc = RTEMS_IO_ERROR; + can_transmit_number transmit_buffer; + + can_enable( can_driver ); + + for ( transmit_buffer = CAN_TRANSMIT1; + ( sc != RTEMS_SUCCESSFUL ) && ( transmit_buffer < + CAN_NUMBER_OF_TRANSMIT_BUFFERS ); + ++transmit_buffer ) { + if ( CANStatus & transmit_info[ transmit_buffer ].can_status_mask ) { + sc = RTEMS_SUCCESSFUL; + obj->transmit[ transmit_buffer ] = *msg; + obj->CMR = transmit_info[ transmit_buffer ].not_cc_cmr_value; + } /*else can buffer busy, try with the next.*/ + } + + return sc; +} + +/** + * @brief Enables the interrupt type passed to the desired CAN device. + * + * @param number The CAN device to enable the interrupts. + * @param type The type of interrupt to enable. + */ +static inline void can_enable_interrupt( + const lpc176x_can_number number, + const can_irq_type type +) +{ + const can_driver_entry *const driver = &can_driver_table[ number ]; + const uint32_t ier = 1 << type; + + can_disable( driver ); + driver->device->IER |= ier; + can_enable( driver ); +} + +rtems_status_code can_register_isr( + const lpc176x_can_number number, + const can_irq_type type, + const lpc176x_can_isr isr +) +{ + rtems_status_code sc = RTEMS_INVALID_NUMBER; + + if ( ( 0 <= type ) && ( type < CAN_IRQ_NUMBER ) ) { + sc = RTEMS_SUCCESSFUL; + isr_vector[ type ] = isr; + can_enable_interrupt( number, type ); + } + + return sc; +} + +rtems_status_code create_can_message( + can_message *const msg, + const int _id, + const char *const _data, + const char _len +) +{ + rtems_status_code sc = RTEMS_INVALID_NUMBER; + + if ( ( _len <= CAN_MAXIMUM_DATA_SIZE ) && ( _id <= CAN10_MAXIMUM_ID ) ) { + sc = RTEMS_SUCCESSFUL; + msg->low_level.dlc = _len; + msg->low_level.type = CANStandard; + msg->low_level.rtr = CANData; + msg->low_level.id = _id; + memcpy( msg->low_level.data, _data, _len ); + } + + return sc; +} + diff --git a/c/src/lib/libbsp/arm/lpc176x/configure.ac b/c/src/lib/libbsp/arm/lpc176x/configure.ac index 7fd04f8..c03013f 100644 --- a/c/src/lib/libbsp/arm/lpc176x/configure.ac +++ b/c/src/lib/libbsp/arm/lpc176x/configure.ac @@ -49,6 +49,9 @@ RTEMS_BSPOPTS_HELP([LPC176X_PCLKDIV],[clock divider for default RTEMS_BSPOPTS_SET([LPC176X_UART_BAUD],[*],[9600U]) RTEMS_BSPOPTS_HELP([LPC176X_UART_BAUD],[baud for UARTs]) +RTEMS_BSPOPTS_SET([LPC176X_CONFIG_UART_1],[*],[1]) +RTEMS_BSPOPTS_HELP([LPC176X_CONFIG_UART_1],[Use Uart 1]) + RTEMS_BSPOPTS_SET([LPC176X_CONFIG_CONSOLE],[*],[0]) RTEMS_BSPOPTS_HELP([LPC176X_CONFIG_CONSOLE],[configuration for console (UART 0)]) diff --git a/c/src/lib/libbsp/arm/lpc176x/console/console-config.c b/c/src/lib/libbsp/arm/lpc176x/console/console-config.c index 3b56a2c..6e1ebc2 100644 --- a/c/src/lib/libbsp/arm/lpc176x/console/console-config.c +++ b/c/src/lib/libbsp/arm/lpc176x/console/console-config.c @@ -62,6 +62,42 @@ static inline void lpc176x_uart_set_register( reg[ i ] = val; } +static bool lpc176x_uart1_probe(rtems_termios_device_context *ctx) +{ + (void)ctx; + + lpc176x_module_enable( LPC176X_MODULE_UART_1, LPC176X_MODULE_PCLK_DEFAULT ); + + lpc176x_pin_select( LPC176X_PIN_UART_1_TXD, LPC176X_PIN_FUNCTION_01 ); + lpc176x_pin_select( LPC176X_PIN_UART_1_RXD, LPC176X_PIN_FUNCTION_01 ); + + return true; +} + +static bool lpc176x_uart2_probe(rtems_termios_device_context *ctx) +{ + (void)ctx; + + lpc176x_module_enable( LPC176X_MODULE_UART_2, LPC176X_MODULE_PCLK_DEFAULT ); + + lpc176x_pin_select( LPC176X_PIN_UART_2_TXD, LPC176X_PIN_FUNCTION_01 ); + lpc176x_pin_select( LPC176X_PIN_UART_2_RXD, LPC176X_PIN_FUNCTION_01 ); + + return true; +} + +static bool lpc176x_uart3_probe(rtems_termios_device_context *ctx) +{ + (void)ctx; + + lpc176x_module_enable( LPC176X_MODULE_UART_3, LPC176X_MODULE_PCLK_DEFAULT ); + + lpc176x_pin_select( LPC176X_PIN_UART_3_TXD, LPC176X_PIN_FUNCTION_10 ); + lpc176x_pin_select( LPC176X_PIN_UART_3_RXD, LPC176X_PIN_FUNCTION_10 ); + + return true; +} + #ifdef LPC176X_CONFIG_CONSOLE static ns16550_context lpc176x_uart_context_0 = { .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"), @@ -126,7 +162,7 @@ const console_device console_device_table[] = { #ifdef LPC176X_CONFIG_UART_1 { .device_file = "/dev/ttyS1", - .probe = ns16550_probe, + .probe = lpc176x_uart1_probe, .handler = &ns16550_handler_interrupt, .context = &lpc176x_uart_context_1.base }, @@ -134,7 +170,7 @@ const console_device console_device_table[] = { #ifdef LPC176X_CONFIG_UART_2 { .device_file = "/dev/ttyS2", - .probe = ns16550_probe, + .probe = lpc176x_uart2_probe, .handler = &ns16550_handler_interrupt, .context = &lpc176x_uart_context_2.base }, @@ -142,7 +178,7 @@ const console_device console_device_table[] = { #ifdef LPC176X_CONFIG_UART_3 { .device_file = "/dev/ttyS3", - .probe = ns16550_probe, + .probe = lpc176x_uart3_probe, .handler = &ns16550_handler_interrupt, .context = &lpc176x_uart_context_3.base }, diff --git a/c/src/lib/libbsp/arm/lpc176x/include/adc-defs.h b/c/src/lib/libbsp/arm/lpc176x/include/adc-defs.h new file mode 100755 index 0000000..04e6a29 --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc176x/include/adc-defs.h @@ -0,0 +1,96 @@ +/** + * @file adc-defs.h + * + * @ingroup lpc176x + * + * @brief ADC library for the lpc176x bsp. + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Diaz Marcos (marcos.d...@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ +#ifndef LPC176X_ADC_DEFS_H +#define LPC176X_ADC_DEFS_H + +#include <bsp.h> +#include <bsp/io.h> +#include <bsp/lpc176x.h> +#include <bsp/adc.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief The ADC inputs of the board. + */ +typedef enum { + ADC_0, + ADC_1, + ADC_2, + ADC_3, + ADC_4, + ADC_5, + ADC_6, + ADC_7, + ADC_DEVICES_COUNT +} lpc176x_adc_number; + +#define MAX_ADC_CLK 13000000u + +#define ADC_RANGE 0xFFFu + +#define ADC_NUMBER_VALID( number ) ( ( (uint32_t) number ) < \ + ADC_DEVICES_COUNT ) + +#define ADC_CR_SEL( val ) BSP_FLD32( val, 0, 7 ) +#define ADC_CR_SEL_GET( val ) BSP_FLD32GET( val, 0, 7 ) +#define ADC_CR_SEL_SET( reg, val ) BSP_FLD32SET( reg, val, 0, 7 ) +#define ADC_CR_CLKDIV( val ) BSP_FLD32( val, 8, 15 ) +#define ADC_CR_CLKDIV_GET( reg ) BSP_FLD32GET( reg, 8, 15 ) +#define ADC_CR_CLKDIV_SET( reg, val ) BSP_FLD32SET( reg, val, 8, 15 ) +#define ADC_CR_BURST BSP_BIT32( 16 ) +#define ADC_CR_CLKS( val ) BSP_FLD32( val, 17, 19 ) +#define ADC_CR_PDN BSP_BIT32( 21 ) +#define ADC_CR_START_NOW BSP_BIT32( 24 ) +#define ADC_CR_START( val ) BSP_FLD32( val, 24, 26 ) +#define ADC_CR_EDGE BSP_BIT32( 27 ) + +#define ADC_DR_VALUE( reg ) BSP_FLD32GET( reg, 4, 15 ) +#define ADC_DR_OVERRUN BSP_BIT32( 30 ) +#define ADC_DR_DONE BSP_BIT32( 31 ) + +#define ADC_DATA_CONVERSION_DONE( val ) ( ( val & ADC_DR_DONE ) != 0u ) + +/** + * @brief The ADC low-level device. + */ +typedef struct { + volatile uint32_t ADCR; + volatile uint32_t ADGDR; + volatile uint32_t RESERVED0; + volatile uint32_t ADINTEN; + volatile uint32_t ADDR[ ADC_DEVICES_COUNT ]; + volatile uint32_t ADSTAT; + volatile uint32_t ADTRM; +} lpc176x_adc_device; + +/** + * @brief Represents the pin and function for each ADC input. + */ +typedef struct { + uint32_t pin_number; + lpc176x_pin_function pin_function; +} lpc176x_adc_pin_map; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/c/src/lib/libbsp/arm/lpc176x/include/adc.h b/c/src/lib/libbsp/arm/lpc176x/include/adc.h new file mode 100755 index 0000000..b8eef42 --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc176x/include/adc.h @@ -0,0 +1,60 @@ +/** + * @file adc.h + * + * @ingroup lpc176x + * + * @brief ADC library for the lpc176x bsp. + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Diaz Marcos (marcos.d...@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef LPC176X_ADC_H +#define LPC176X_ADC_H + +#include <bsp.h> +#include <bsp/common-types.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief Opens and initializes the ADC device. + * + * @param adc_number The ADC pin number to be initialized. + * @return RTEMS_SUCCESSFUL if the initialization was succesful, + * RTEMS_INVALID_NUMBER if wrong parameter. + */ +rtems_status_code adc_open( const lpc176x_pin_number pin_number ); + +/** + * @brief Closes the ADC device. + * + * @return RTEMS_SUCCESSFUL if closed succesfully. + */ +rtems_status_code adc_close( void ); + +/** + * @brief Starts a conversion, waits for it to finish and reads the value. + * + * @param pin_number The port to read the value. + * @param result The read result. (In a percentage between 0.0f and 1.0f). + */ +rtems_status_code adc_read( + const lpc176x_pin_number pin_number , + float *const result +); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/c/src/lib/libbsp/arm/lpc176x/include/can-defs.h b/c/src/lib/libbsp/arm/lpc176x/include/can-defs.h new file mode 100755 index 0000000..aee980a --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc176x/include/can-defs.h @@ -0,0 +1,183 @@ +/** + * @file can-defs.h + * + * @ingroup lpc176x + * + * @brief CAN controller for the lpc176x controller. + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Diaz Marcos (marcos.d...@tallertechnologies.com) + * @author Daniel Chicco (daniel.chi...@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef LPC176X_TIMER_DEFS_H +#define LPC176X_TIMER_DEFS_H + +#include <bsp/common-types.h> +#include <bsp/can.h> + +/* CAN ACCEPTANCE FILTER */ +#define CAN_ACCEPT_BASE_ADDR 0x4003C000 + +#define CAN_DRIVER_IS_MINOR_VALID( minor ) ( minor < CAN_DEVICES_NUMBER ) +#define CAN_DEFAULT_BAUD_RATE 1000000u +#define CAN_DEFAULT_INTERRUPT_CONFIGURATION 0 + +#define MAX_NUMBER_OF_CAN_BITS 25u +#define MIN_NUMBER_OF_CAN_BITS 4u +#define CAN_BRP_EXTRA_BIT 1u +#define CAN_TSEG_EXTRA_BITS 3u +#define MAX_TSEG1_TSEG2_BITS 22u + +#define CAN_GSR_RBS_MASK 1u +#define CAN_CMR_RRB_MASK 4u + +#define CAN_MAXIMUM_DATA_SIZE 8u +#define CAN10_MAXIMUM_ID 0x7FFu + +/** + * @brief The Time segments of a CAN bit. + */ +typedef enum { + CAN_TSEG1, + CAN_TSEG2, + CAN_NUMBER_OF_TSEG, +} can_tseg_number; + +#define CAN_BTR_TSEG1_SHIFT 16u +#define CAN_BTR_TSEG2_SHIFT 20u +#define CAN_BTR_SJW_SHIFT 14u +#define CAN_BTR_BRP_SHIFT 0u + +#define CAN_BTR_TSEG1_MASK 0x000F0000U +#define CAN_BTR_TSEG2_MASK 0x00700000U +#define CAN_BTR_SJW_MASK 0x0000C000U +#define CAN_BTR_BRP_MASK 0x000003FFU + +#define WRONG_BTR_VALUE 0xFFFFFFFF + +/** + * @brief The transmit buffers of the CAN device. + */ +typedef enum { + CAN_TRANSMIT1, + CAN_TRANSMIT2, + CAN_TRANSMIT3, + CAN_NUMBER_OF_TRANSMIT_BUFFERS +} can_transmit_number; + +/** + * @brief The CAN status and control masks to send a message + * for each transmit buffer. + */ +typedef struct { + uint32_t can_status_mask; + uint32_t not_cc_cmr_value; +} can_transmit_info; + +/** @brief Represents the CAN controller registers.*/ +typedef struct { + volatile uint32_t MOD; + volatile uint32_t CMR; + volatile uint32_t GSR; + volatile uint32_t ICR; + volatile uint32_t IER; + volatile uint32_t BTR; + volatile uint32_t EWL; + volatile uint32_t SR; + volatile registers_can_message receive; + volatile registers_can_message transmit[ CAN_NUMBER_OF_TRANSMIT_BUFFERS ]; +} can_device; + +/** + * @brief A TX or RX pin for each CAN device . + */ +typedef enum { + CAN_TX_PIN, + CAN_RX_PIN, + NUMBER_OF_CAN_PINS +} can_pin_number; + +/** + * @brief A driver entry for each low level device. + */ +typedef struct { + can_device *const device; + const lpc176x_module module; + const uint32_t pconp_pin; + const uint32_t pins[ NUMBER_OF_CAN_PINS ]; + const lpc176x_pin_function pinfunction; +} can_driver_entry; + +/** @brief Represents the CAN centralized registers. */ +typedef struct { + volatile uint32_t TX_SR; + volatile uint32_t RX_SR; + volatile uint32_t MSR; +} can_central; + +/** @brief Represents the acceptance filter registers. */ +typedef struct { + volatile uint32_t AFMR; + volatile uint32_t SFF_SA; + volatile uint32_t SFF_GRP_SA; + volatile uint32_t EFF_SA; + volatile uint32_t EFF_GRP_SA; + volatile uint32_t EOT; + volatile uint32_t LUT_ERR_ADR; + volatile uint32_t LUT_ERR; + volatile uint32_t FCANIE; + volatile uint32_t FCANIC0; + volatile uint32_t FCANIC1; +} can_acceptance_filter; + +/** + * @brief The possible CAN formats for a message. + */ +typedef enum { + CANStandard = 0, + CANExtended = 1, + CANAny = 2 +} can_format; + +/** + * @brief The types of message. + */ +typedef enum { + CANData = 0, + CANRemote = 1 +} can_type; + +#define CAN_INTERRUPT_TYPE_MASK 0x1ffu + +/** + * @brief The vector with all the callbacks for the CAN isr. + */ +typedef lpc176x_can_isr lpc176x_can_isr_vector[ CAN_IRQ_NUMBER ]; + +#define CAN_MOD_RM 0x00000001U + +#define CAN_ACCF_AFMR_ACCOF 0x00000001U +#define CAN_ACCF_AFMR_ACCBP 0x00000002U +#define CAN_ACCF_AFMR_EFCAN 0x00000004U + +#define CAN_IER_RIE 0x000000001U +#define CAN_IER_TIE1 0x000000002U +#define CAN_IER_EIE 0x000000004U +#define CAN_IER_DOIE 0x000000008U +#define CAN_IER_WUIE 0x000000010U +#define CAN_IER_EPIEX 0x000000020U +#define CAN_IER_ALIEX 0x000000040U +#define CAN_IER_BEIEX 0x000000080U +#define CAN_IER_IDIEX 0x000000100U +#define CAN_IER_TIE2 0x000000200U +#define CAN_IER_TIE3 0x000000400U + +#endif /*LPC176X_TIMER_DEFS_H*/ diff --git a/c/src/lib/libbsp/arm/lpc176x/include/can.h b/c/src/lib/libbsp/arm/lpc176x/include/can.h new file mode 100755 index 0000000..de3fa55 --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc176x/include/can.h @@ -0,0 +1,179 @@ +/** + * @file can.h + * + * @ingroup lpc176x + * + * @brief CAN controller for the mbed lpc1768 board. + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Diaz Marcos (marcos.d...@tallertechnologies.com) + * @author Daniel Chicco (daniel.chi...@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef LPC176X_CAN_H +#define LPC176X_CAN_H + +#include <bsp.h> +#include <bsp/io.h> +#include <bsp/lpc176x.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief The CAN devices of the board. + */ +typedef enum { + CAN_0, + CAN_1, + CAN_DEVICES_NUMBER +} lpc176x_can_number; + +/** + * @brief A CAN message represented for the registers of the device. + */ +typedef struct { + uint32_t info; + uint32_t id; + uint32_t data_a; + uint32_t data_b; +} registers_can_message; + +/** + * @brief A CAN message represented with each logical parts + */ +typedef struct { + unsigned int reserved1 : 16; + unsigned int dlc : 4; /* Bits 16..19: DLC - Data Length Counter*/ + unsigned int reserved0 : 10; + unsigned int rtr : 1; /* Bit 30: Set if this is a RTR message*/ + unsigned int type : 1; /* Bit 31: Set if this is a 29-bit ID message*/ + unsigned int id; /* CAN Message ID (11-bit or 29-bit)*/ + unsigned char data[ 8 ]; /* CAN Message Data Bytes 0-7*/ +} low_level_can_message; + +/** + * @brief A CAN message represented of both forms. + */ +typedef union { + low_level_can_message low_level; + registers_can_message registers; +} can_message; + +/** + * @brief The possible interrupt sources for CAN. + */ +typedef enum { + IRQ_RX = 0, + IRQ_TX, + IRQ_ERROR, + IRQ_OVERRUN, + IRQ_WAKEUP, + IRQ_PASSIVE, + IRQ_ARB, + IRQ_BUS, + IRQ_READY, + CAN_IRQ_NUMBER +} can_irq_type; + +/** + * @brief An isr for a CAN interrupt + * + * @param number The CAN which rised the interrupt. + */ +typedef void (*lpc176x_can_isr) ( lpc176x_can_number number ); + +/** + * @brief A CAN frequency value + */ +typedef unsigned int can_freq; + +/** + * @brief Opens CAN device. + * @details It enables the module and gives it a clock, sets the pins, + * disables the interrupts, sets the frequency and bypasses + * the acceptance filter. + * + * @param minor The device to open. + * @param freq The desired frequency. + * @return RTEMS_SUCCESFUL on success. + */ +rtems_status_code can_open( lpc176x_can_number minor, can_freq freq ); + +/** + * @brief Closes the passed CAN device and shut it down. + * + * @param minor The device to close. + * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_NUMBER for a bad parameter. + */ +rtems_status_code can_close( lpc176x_can_number minor ); + +/** + * @brief Reads the CAN device. + * + * @param minor The CAN device to read. + * @param message The read message. + * @return RTEMS_SUCCESSFUL if read ok, RTEMS_IO_ERROR otherwise. + */ +rtems_status_code can_read( + const lpc176x_can_number minor, + can_message *message +); + +/** + * @brief Writes the passed CAN message into the selected CAN device. + * + * @param minor The device to write. + * @param message The message to write. + * @return RTEMS_SUCCESFUL if write ok. RTEMS_IO_ERROR otherwise. + */ +rtems_status_code can_write( + const lpc176x_can_number minor, + const can_message *const message +); + +/** + * @brief Registers an isr in the driver vector, and enables the interrupt +* in the device. + * + * @param number The CAN device to set + * @param type The interrupt type. + * @param isr The isr to register. + * @return RTEMS_SUCCESSFUL if ok RTEMS_INVALID_NUMBER otherwise. + */ +rtems_status_code can_register_isr( + const lpc176x_can_number number, + const can_irq_type type, + const lpc176x_can_isr isr +); + +/** + * @brief Creates a CAN message. + * @details [long description] + * + * @param msg The created message. + * @param _id The can id for the message. + * @param _data The data of the message. + * @param _len The lenght of the message. + * @return RTEMS_SUCCESFUL if created, RTEMS_INVALID_NUMBER otherwise. + */ +rtems_status_code create_can_message( + can_message *const msg, + const int _id, + const char *const _data, + const char _len +); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* ifndef LPC176X_CAN_H */ diff --git a/c/src/lib/libbsp/arm/lpc176x/include/common-types.h b/c/src/lib/libbsp/arm/lpc176x/include/common-types.h index dec487c..ad6b4ed 100644 --- a/c/src/lib/libbsp/arm/lpc176x/include/common-types.h +++ b/c/src/lib/libbsp/arm/lpc176x/include/common-types.h @@ -46,6 +46,7 @@ typedef enum { LPC176X_MODULE_ADC, LPC176X_MODULE_CAN_0, LPC176X_MODULE_CAN_1, + LPC176X_MODULE_ACCF, LPC176X_MODULE_DAC, LPC176X_MODULE_GPDMA, LPC176X_MODULE_GPIO, diff --git a/c/src/lib/libbsp/arm/lpc176x/include/io-defs.h b/c/src/lib/libbsp/arm/lpc176x/include/io-defs.h index a0afdf4..fd8fcf6 100644 --- a/c/src/lib/libbsp/arm/lpc176x/include/io-defs.h +++ b/c/src/lib/libbsp/arm/lpc176x/include/io-defs.h @@ -43,6 +43,12 @@ extern "C" { #define LPC176X_PIN_SELECT_MASK_SIZE 2U #define LPC176X_PIN_UART_0_TXD 2U #define LPC176X_PIN_UART_0_RXD 3U +#define LPC176X_PIN_UART_1_TXD 15U +#define LPC176X_PIN_UART_1_RXD 16U +#define LPC176X_PIN_UART_2_TXD 10U +#define LPC176X_PIN_UART_2_RXD 11U +#define LPC176X_PIN_UART_3_TXD 0U +#define LPC176X_PIN_UART_3_RXD 1U #define LPC176X_MODULE_BITS_COUNT 32U #define LPC176X_MODULE_COUNT ( LPC176X_MODULE_USB + 1U ) @@ -69,6 +75,19 @@ typedef enum { lpc176x_pin_function; /** + * @brief Defines the pin modes. + * + */ +typedef enum { + LPC176X_PIN_MODE_PULLUP, + LPC176X_PIN_MODE_REPEATER, + LPC176X_PIN_MODE_NONE, + LPC176X_PIN_MODE_PULLDOWN, + LPC176X_PIN_MODE_COUNT +} +lpc176x_pin_mode; + +/** * @brief Defines all type of pins. * * Enumerated type to define the set of pin type for a io device. diff --git a/c/src/lib/libbsp/arm/lpc176x/include/io.h b/c/src/lib/libbsp/arm/lpc176x/include/io.h index e7c0dd0..9538372 100644 --- a/c/src/lib/libbsp/arm/lpc176x/include/io.h +++ b/c/src/lib/libbsp/arm/lpc176x/include/io.h @@ -31,7 +31,7 @@ extern "C" { #endif /* __cplusplus */ /** - * @brief Set pin to the selected function. + * @brief Sets pin to the selected function. * * @param pin The pin to set. * @param function Defines the function to set. @@ -42,6 +42,17 @@ void lpc176x_pin_select( ); /** + * @brief Sets pin to the selected mode. + * + * @param pin The pin to set. + * @param mode Defines the mode to set. + */ +void lpc176x_pin_set_mode( + const uint32_t pin, + const lpc176x_pin_mode mode +); + +/** * @brief Enables the module power and clock. * * @param module Represents the module to be enabled. diff --git a/c/src/lib/libbsp/arm/lpc176x/include/lpc176x.h b/c/src/lib/libbsp/arm/lpc176x/include/lpc176x.h index 951c33b..99395b8 100644 --- a/c/src/lib/libbsp/arm/lpc176x/include/lpc176x.h +++ b/c/src/lib/libbsp/arm/lpc176x/include/lpc176x.h @@ -176,12 +176,12 @@ typedef struct { #define LPC176X_SCB_PBOOST_BOOST BSP_BIT32( 0 ) #define LPC176X_SCB_CLKOUTCFG_CLKOUTSEL( val ) BSP_FLD32( val, 3, 0 ) #define LPC176X_SCB_CLKOUTCFG_CLKOUTSEL_GET( reg ) BSP_FLD32GET( reg, 3, 0 ) -#define LPC176X_SCB_CLKOUTCFG_CLKOUTSEL_SET( reg, val ) BSP_FLD32SET( reg, val, \ - 3, 0 ) +#define LPC176X_SCB_CLKOUTCFG_CLKOUTSEL_SET( reg, val ) BSP_FLD32SET( reg, \ + val, 3, 0 ) #define LPC176X_SCB_CLKOUTCFG_CLKOUTDIV( val ) BSP_FLD32( val, 7, 4 ) #define LPC176X_SCB_CLKOUTCFG_CLKOUTDIV_GET( reg ) BSP_FLD32GET( reg, 7, 4 ) -#define LPC176X_SCB_CLKOUTCFG_CLKOUTDIV_SET( reg, val ) BSP_FLD32SET( reg, val, \ - 7, 4 ) +#define LPC176X_SCB_CLKOUTCFG_CLKOUTDIV_SET( reg, val ) BSP_FLD32SET( reg, \ + val, 7, 4 ) #define LPC176X_SCB_CLKOUTCFG_CLKOUT_EN BSP_BIT32( 8 ) #define LPC176X_SCB_CLKOUTCFG_CLKOUT_ACT BSP_BIT32( 9 ) diff --git a/c/src/lib/libbsp/arm/lpc176x/include/mbed-pinmap.h b/c/src/lib/libbsp/arm/lpc176x/include/mbed-pinmap.h new file mode 100755 index 0000000..9534334 --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc176x/include/mbed-pinmap.h @@ -0,0 +1,50 @@ +/** + * @file mbed-pinmap.h + * + * @ingroup lpc176x + * + * @brief Pins of the mbed lpc1768 + * See http://mbed.org/media/uploads/chris/mbed-005.1.pdf for references + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Diaz Marcos (marcos.d...@tallertechnologies.com) + * @author Daniel Chicco (daniel.chi...@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#define DIP5 9U +#define DIP6 8U +#define DIP7 7U +#define DIP8 6U +#define DIP9 0U +#define DIP10 1U +#define DIP11 18U +#define DIP12 17U +#define DIP13 15U +#define DIP14 16U +#define DIP15 23U +#define DIP16 24U +#define DIP17 25U +#define DIP18 26U +#define DIP19 62U +#define DIP20 63U +#define DIP21 69U +#define DIP22 68U +#define DIP23 67U +#define DIP24 66U +#define DIP25 65U +#define DIP26 64U +#define DIP27 11U +#define DIP28 10U +#define DIP29 5U +#define DIP30 4U +#define LED1 50U +#define LED2 52U +#define LED3 53U +#define LED4 55U diff --git a/c/src/lib/libbsp/arm/lpc176x/include/pwmout-defs.h b/c/src/lib/libbsp/arm/lpc176x/include/pwmout-defs.h new file mode 100755 index 0000000..414e8b7 --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc176x/include/pwmout-defs.h @@ -0,0 +1,105 @@ +/** + * @file pwmout-defs.h + * + * @ingroup lpc176x + * + * @brief PWM-Out controller for the mbed lpc1768 board. + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Diaz Marcos (marcos.d...@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef LPC176X_PWMOUT_DEFS_H +#define LPC176X_PWMOUT_DEFS_H + +#include <bsp/lpc176x.h> +#include <bsp/pwmout.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define PWM_DEFAULT_PERIOD 20000u +#define PWM_DEFAULT_PULSEWIDTH 0u + +#define PWM_PRESCALER_USECOND ( LPC176X_CCLK / 1000000 ) +#define PWM_MCR_RESET_ON_MATCH0 ( 1 << 1 ) +#define PWM_PCR_ENABLE_PWM( pwmout ) ( 1 << ( 9 + pwmout ) ) +#define PWM_TCR_RESET ( 1 << 1 ) +#define PWM_TCR_ENABLE ( 1u ) +#define PWM_TCR_PWM ( 1 << 3 ) +#define PWM_LER_LATCH_MATCH_0 1u +#define PWM_LER_LATCH( match ) ( 1 << ( ( match ) + 1 ) ) + +/** + * @brief The low-level PWM output device. + */ +typedef struct { + volatile uint32_t IR; + volatile uint32_t TCR; + volatile uint32_t TC; + volatile uint32_t PR; + volatile uint32_t PC; + volatile uint32_t MCR; + volatile uint32_t MR0; + volatile uint32_t MR1; + volatile uint32_t MR2; + volatile uint32_t MR3; + volatile uint32_t CCR; + volatile uint32_t CR0; + volatile uint32_t CR1; + volatile uint32_t CR2; + volatile uint32_t CR3; + volatile uint32_t RESERVED0; + volatile uint32_t MR4; + volatile uint32_t MR5; + volatile uint32_t MR6; + volatile uint32_t PCR; + volatile uint32_t LER; + volatile uint32_t RESERVED1[ 7 ]; + volatile uint32_t CTCR; +} lpc176x_pwm_device; + +/** + * @brief Represents one pin and the respective function to be set + * for each PWM output. + */ +typedef struct { + uint32_t pin_number; + lpc176x_pin_function pin_function; +} lpc176x_pwm_pin; + +/** + * @brief The PWM outputs of the board. + */ +typedef enum { + PWMO_1, + PWMO_2, + PWMO_3, + PWMO_4, + PWMO_5, + PWMO_6, + PWM_OUTPUT_NUMBER +} lpc176x_pwm_number; + +/** + * @brief A pin for each PWM output. + */ +typedef enum { + PWM_FIRST_PIN, + PWM_SECOND_PIN, + PWM_NUMBER_OF_PINS +} lpc176x_pwm_pin_number; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/c/src/lib/libbsp/arm/lpc176x/include/pwmout.h b/c/src/lib/libbsp/arm/lpc176x/include/pwmout.h new file mode 100755 index 0000000..4c18700 --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc176x/include/pwmout.h @@ -0,0 +1,73 @@ +/** + * @file pwmout.h + * + * @ingroup lpc176x + * + * @brief PWM-Out controller for the mbed lpc1768 board. + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Diaz Marcos (marcos.d...@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef LPC176X_PWMOUT_H +#define LPC176X_PWMOUT_H + +#include <bsp.h> +#include <bsp/io.h> +#include <bsp/lpc176x.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief Initializes the PWM output device and sets an initial period + * of 20000us. + * + * @param pin_number The PWM output pin. + * @return RTEMS_SUCCESSFULL if the PWM initialization was OK, + * RTEMS_INVALID_NUMBER for a wrong parameter. + */ +rtems_status_code pwm_init( const lpc176x_pin_number pin_number ); + +/** + * @brief Sets a period for the PWM output. (Note that this changes the period + * for all the PWM outputs.) + * + * @param pin_number The pin whose period we want to change. + * @param period The desired period in microseconds. + * + * @return RTEMS_SUCCESSFULL if the period's setting was OK, + * RTEMS_INVALID_NUMBER for a bad parameter. + */ +rtems_status_code pwm_period( + const lpc176x_pin_number pin_number, + const lpc176x_microseconds period +); + +/** + * @brief Sets a pulsewidth for the PWM output. + * + * @param pin_number The pin whose pulsewidth we want to change. + * @param pwidth The desired pulsewidth in microseconds. + * + * @return RTEMS_SUCCESSFULL if the pulsewidth's setting was OK, + * RTEMS_INVALID_NUMBER for a wrong parameter. + */ +rtems_status_code pwm_pulsewidth( + const lpc176x_pin_number pin_number, + const lpc176x_microseconds pwidth +); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/c/src/lib/libbsp/arm/lpc176x/misc/io.c b/c/src/lib/libbsp/arm/lpc176x/misc/io.c index 59b357d..7acab0a 100644 --- a/c/src/lib/libbsp/arm/lpc176x/misc/io.c +++ b/c/src/lib/libbsp/arm/lpc176x/misc/io.c @@ -33,6 +33,7 @@ static const lpc176x_module_entry lpc176x_module_table[] = { LPC176X_MODULE_ENTRY( LPC176X_MODULE_ADC, 1, 1, 12 ), LPC176X_MODULE_ENTRY( LPC176X_MODULE_CAN_0, 1, 1, 13 ), LPC176X_MODULE_ENTRY( LPC176X_MODULE_CAN_1, 1, 1, 14 ), + LPC176X_MODULE_ENTRY(LPC176X_MODULE_ACCF, 0, 1, 15), LPC176X_MODULE_ENTRY( LPC176X_MODULE_DAC, 0, 1, 11 ), LPC176X_MODULE_ENTRY( LPC176X_MODULE_GPDMA, 1, 1, 29 ), LPC176X_MODULE_ENTRY( LPC176X_MODULE_GPIO, 0, 1, 15 ), @@ -70,6 +71,20 @@ inline void lpc176x_pin_select( LPC176X_PIN_SELECT_MASK << shift, shift ); } +void lpc176x_pin_set_mode( + const uint32_t pin, + const lpc176x_pin_mode mode +) +{ + assert( pin <= LPC176X_IO_INDEX_MAX + && mode < LPC176X_PIN_MODE_COUNT ); + const uint32_t pin_selected = LPC176X_PIN_SELECT( pin ); + volatile uint32_t *const pinmode = &LPC176X_PINMODE[ pin_selected ]; + const uint32_t shift = LPC176X_PIN_SELECT_SHIFT( pin ); + *pinmode = SET_FIELD( *pinmode, mode, + LPC176X_PIN_SELECT_MASK << shift, shift ); +} + /** * @brief Checks if the module has power. * diff --git a/c/src/lib/libbsp/arm/lpc176x/preinstall.am b/c/src/lib/libbsp/arm/lpc176x/preinstall.am index f28c8d5..5c86c8b 100644 --- a/c/src/lib/libbsp/arm/lpc176x/preinstall.am +++ b/c/src/lib/libbsp/arm/lpc176x/preinstall.am @@ -117,6 +117,30 @@ $(PROJECT_INCLUDE)/bsp/gpio.h: include/gpio.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/gpio.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/gpio.h +$(PROJECT_INCLUDE)/bsp/can.h: include/can.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/can.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/can.h + +$(PROJECT_INCLUDE)/bsp/can-defs.h: include/can-defs.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/can-defs.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/can-defs.h + +$(PROJECT_INCLUDE)/bsp/pwmout.h: include/pwmout.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/pwmout.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/pwmout.h + +$(PROJECT_INCLUDE)/bsp/pwmout-defs.h: include/pwmout-defs.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/pwmout-defs.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/pwmout-defs.h + +$(PROJECT_INCLUDE)/bsp/adc.h: include/adc.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/adc.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/adc.h + +$(PROJECT_INCLUDE)/bsp/adc-defs.h: include/adc-defs.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/adc-defs.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/adc-defs.h + $(PROJECT_INCLUDE)/bsp/timer-defs.h: include/timer-defs.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/timer-defs.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/timer-defs.h @@ -149,6 +173,10 @@ $(PROJECT_INCLUDE)/bsp/system-clocks.h: include/system-clocks.h $(PROJECT_INCLUD $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/system-clocks.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/system-clocks.h +$(PROJECT_INCLUDE)/bsp/mbed-pinmap.h: include/mbed-pinmap.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/mbed-pinmap.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/mbed-pinmap.h + $(PROJECT_INCLUDE)/tm27.h: ../../shared/include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h diff --git a/c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c b/c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c new file mode 100755 index 0000000..a368386 --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c @@ -0,0 +1,210 @@ +/** + * @file pwmout.c + * + * @ingroup lpc176x + * + * @brief PWM-Out controller for the mbed lpc1768 board. + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Diaz Marcos (marcos.d...@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include <rtems/status-checks.h> +#include <bsp/pwmout.h> +#include <bsp/pwmout-defs.h> + +/** + * @brief The low level device. + */ +static lpc176x_pwm_device *const pwm_device = PWM1_BASE_ADDR; + +/** + * @brief The possible output pins for each PWM output. + */ +static const lpc176x_pwm_pin pwm_pins[ PWM_OUTPUT_NUMBER ][ PWM_NUMBER_OF_PINS +] = +{ + { { 50u, LPC176X_PIN_FUNCTION_10 }, { 64u, LPC176X_PIN_FUNCTION_01 } }, + { { 52u, LPC176X_PIN_FUNCTION_10 }, { 65u, LPC176X_PIN_FUNCTION_01 } }, + { { 53u, LPC176X_PIN_FUNCTION_10 }, { 66u, LPC176X_PIN_FUNCTION_01 } }, + { { 55u, LPC176X_PIN_FUNCTION_10 }, { 67u, LPC176X_PIN_FUNCTION_01 } }, + { { 56u, LPC176X_PIN_FUNCTION_10 }, { 68u, LPC176X_PIN_FUNCTION_01 } }, + { { 58u, LPC176X_PIN_FUNCTION_10 }, { 69u, LPC176X_PIN_FUNCTION_01 } }, +}; + +/** + * @brief The pointers to the low level match registers for each PWM output. + */ +static volatile uint32_t *const pwm_match[ PWM_OUTPUT_NUMBER ] = { + &PWM1MR1, + &PWM1MR2, + &PWM1MR3, + &PWM1MR4, + &PWM1MR5, + &PWM1MR6 +}; + +/** + * @brief Checks if a pin number is valid for the given PWM, + * and sets the corresponding pin function for that pin. + * + * @param pin_number The pin number to search. + * @param pwm In which PWM search for the pin number. + * @param pin_function If the pin number is found, here we return + * the pin function for that pin number. + * @return True if found, false otherwise. + */ +static inline bool is_found_in_this_pwm( + const lpc176x_pin_number pin_number, + const lpc176x_pwm_number pwm, + lpc176x_pin_function *const pin_function +) +{ + lpc176x_pwm_pin_number pnumber = PWM_FIRST_PIN; + bool found = false; + + while (!found && ( pnumber < PWM_NUMBER_OF_PINS )) + { + if ( pwm_pins[ pwm ][ pnumber ].pin_number == pin_number ) { + found = true; + *pin_function = pwm_pins[ pwm ][ pnumber ].pin_function; + }/*else implies that the pin number was not found. Keep looking.*/ + ++pnumber; + } + return found; +} + +/** + * @brief Checks if a pin number is valid for any PWM, + * and sets the corresponding pin function for that pin. + * + * @param pin_number The pin number to search. + * @param pwm If is found here we return in which PWM was found. + * @param pin_function If the pin number is found the pin function + * for this pin number one will be returned. + * @return True if found, false otherwise. + */ +static bool is_valid_pin_number( + const lpc176x_pin_number pin_number, + lpc176x_pwm_number *const pwm, + lpc176x_pin_function *const pin_function +) +{ + bool found = false; + lpc176x_pwm_number pwm_local = PWMO_1; + while(!found && ( pwm_local < PWM_OUTPUT_NUMBER )) + { + if ( is_found_in_this_pwm( pin_number, pwm_local, pin_function ) ) { + *pwm = pwm_local; + found = true; + } /*else implies that the pin number was not found. Keep looking.*/ + ++pwm_local; + } + + return found; +} + +/** + * @brief Sets the period for the given PWM. + * + * @param pwm The PWM output in which the period will be set. + * @param period The period to set. + */ +static void set_period( + const lpc176x_pwm_number pwm, + const lpc176x_microseconds period +) +{ + pwm_device->TCR = PWM_TCR_RESET; + pwm_device->MR0 = period * PWM_PRESCALER_USECOND; + pwm_device->LER |= PWM_LER_LATCH_MATCH_0; + pwm_device->TCR = PWM_TCR_PWM | PWM_TCR_ENABLE; +} + +/** + * @brief Sets the pulsewidth for the given PWM. + * + * @param pwm The PWM output in which the pulsewidth will be set. + * @param pwidth The pulse width to set. + */ +static void set_pulsewidth( + const lpc176x_pwm_number pwm, + lpc176x_microseconds pwidth +) +{ + pwidth *= PWM_PRESCALER_USECOND; + + if ( pwm_device->MR0 == pwidth ) { + ++pwidth; + } /* Not the same as the period, do nothing.*/ + + *( pwm_match[ pwm ] ) = pwidth; + pwm_device->LER |= PWM_LER_LATCH( pwm ); +} + +rtems_status_code pwm_init( const lpc176x_pin_number pin_number ) +{ + rtems_status_code sc = RTEMS_INVALID_NUMBER; + lpc176x_pin_function pin_function; + lpc176x_pwm_number pwm; + + if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) { + sc = lpc176x_module_enable( LPC176X_MODULE_PWM_1, + LPC176X_MODULE_PCLK_DEFAULT ); + RTEMS_CHECK_SC( sc, "enable pwm module" ); + + pwm_device->PR = 0; + pwm_device->MCR = PWM_MCR_RESET_ON_MATCH0; + pwm_device->PCR |= PWM_PCR_ENABLE_PWM( pwm ); + + set_period( pwm, PWM_DEFAULT_PERIOD ); + set_pulsewidth( pwm, PWM_DEFAULT_PULSEWIDTH ); + + lpc176x_pin_select( pin_number, pin_function ); + } /* else implies that the pin number is not valid. + So, a RTEMS_INVALID_NUMBER will be returned.*/ + + return sc; +} + +rtems_status_code pwm_period( + const lpc176x_pin_number pin_number, + const lpc176x_microseconds period +) +{ + rtems_status_code sc = RTEMS_INVALID_NUMBER; + lpc176x_pin_function pin_function; + lpc176x_pwm_number pwm; + + if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) { + sc = RTEMS_SUCCESSFUL; + set_period( pwm, period ); + } /* else implies that the pin number is not valid. + So, a RTEMS_INVALID_NUMBER will be returned.*/ + + return sc; +} + +rtems_status_code pwm_pulsewidth( + const lpc176x_pin_number pin_number, + const lpc176x_microseconds pwidth +) +{ + rtems_status_code sc = RTEMS_INVALID_NUMBER; + lpc176x_pin_function pin_function; + lpc176x_pwm_number pwm; + + if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) { + sc = RTEMS_SUCCESSFUL; + set_pulsewidth( pwm, pwidth ); + } /* Else wrong pin_number return RTEMS_INVALID_NUMBER*/ + + return sc; +} diff --git a/c/src/lib/libbsp/shared/include/uart-output-char.h b/c/src/lib/libbsp/shared/include/uart-output-char.h index 4242901..a6648d1 100644 --- a/c/src/lib/libbsp/shared/include/uart-output-char.h +++ b/c/src/lib/libbsp/shared/include/uart-output-char.h @@ -51,8 +51,8 @@ CONSOLE_LCR = 0x00; \ CONSOLE_IER = 0x00; \ CONSOLE_LCR = 0x80; \ - CONSOLE_DLL = (dll); \ - CONSOLE_DLM = 0x00; \ + CONSOLE_DLL = (dll & 0xFF); \ + CONSOLE_DLM = (dll >> 8); \ CONSOLE_LCR = 0x03; \ CONSOLE_FCR = 0x07; \ } while (0) -- 2.3.2 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel