diff options
Diffstat (limited to 'os')
| -rw-r--r-- | os/hal/platforms/LPC11xx/ext_lld.c | 259 | ||||
| -rw-r--r-- | os/hal/platforms/LPC11xx/ext_lld.h | 185 | ||||
| -rw-r--r-- | os/hal/platforms/LPC11xx/ext_lld_isr.c | 176 | ||||
| -rw-r--r-- | os/hal/platforms/LPC11xx/ext_lld_isr.h | 111 | ||||
| -rw-r--r-- | os/hal/platforms/LPC11xx/i2c_lld.c | 438 | ||||
| -rw-r--r-- | os/hal/platforms/LPC11xx/i2c_lld.h | 225 | ||||
| -rw-r--r-- | os/hal/platforms/LPC11xx/platform.mk | 6 | ||||
| -rw-r--r-- | os/hal/platforms/LPC11xx/pwm_lld.c | 407 | ||||
| -rw-r--r-- | os/hal/platforms/LPC11xx/pwm_lld.h | 364 | ||||
| -rw-r--r-- | os/ports/GCC/ARMCMx/LPC11xx/ld/LPC11C24.ld | 152 | 
10 files changed, 2322 insertions, 1 deletions
diff --git a/os/hal/platforms/LPC11xx/ext_lld.c b/os/hal/platforms/LPC11xx/ext_lld.c new file mode 100644 index 000000000..c22cd83be --- /dev/null +++ b/os/hal/platforms/LPC11xx/ext_lld.c @@ -0,0 +1,259 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
 +    LPC11xx EXT driver - Copyright (C) 2013 Marcin Jokel
 +
 +    Licensed under the Apache License, Version 2.0 (the "License");
 +    you may not use this file except in compliance with the License.
 +    You may obtain a copy of the License at
 +
 +        http://www.apache.org/licenses/LICENSE-2.0
 +
 +    Unless required by applicable law or agreed to in writing, software
 +    distributed under the License is distributed on an "AS IS" BASIS,
 +    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 +    See the License for the specific language governing permissions and
 +    limitations under the License.
 +*/
 +
 +/**
 + * @file    LPC11xx/ext_lld.c
 + * @brief   LPC11xx EXT subsystem low level driver source.
 + *
 + * @addtogroup EXT
 + * @{
 + */
 +
 +#include "ch.h"
 +#include "hal.h"
 +
 +#if HAL_USE_EXT || defined(__DOXYGEN__)
 +
 +#include "ext_lld_isr.h"
 +
 +/*===========================================================================*/
 +/* Driver local definitions.                                                 */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver exported variables.                                                */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   EXTD0 driver identifier.
 + */
 +#if LPC11xx_EXT_USE_EXT0 || defined(__DOXYGEN__)
 +EXTDriver EXTD0;
 +#endif
 +
 +/**
 + * @brief   EXTD1 driver identifier.
 + */
 +#if LPC11xx_EXT_USE_EXT1 || defined(__DOXYGEN__)
 +EXTDriver EXTD1;
 +#endif
 +
 +/**
 + * @brief   EXTD2 driver identifier.
 + */
 +#if LPC11xx_EXT_USE_EXT2 || defined(__DOXYGEN__)
 +EXTDriver EXTD2;
 +#endif
 +
 +/**
 + * @brief   EXTD3 driver identifier.
 + */
 +#if LPC11xx_EXT_USE_EXT3 || defined(__DOXYGEN__)
 +EXTDriver EXTD3;
 +#endif
 +
 +/*===========================================================================*/
 +/* Driver local variables and types.                                         */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver local functions.                                                   */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver interrupt handlers.                                                */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver exported functions.                                                */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   Low level EXT driver initialization.
 + *
 + * @notapi
 + */
 +void ext_lld_init(void) {
 +
 +  /* Driver initialization.*/
 +#if LPC11xx_EXT_USE_EXT0
 +  extObjectInit(&EXTD0);
 +  EXTD0.gpio = LPC_GPIO0;
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT1
 +  extObjectInit(&EXTD1);
 +  EXTD1.gpio = LPC_GPIO1;
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT2
 +  extObjectInit(&EXTD2);
 +  EXTD2.gpio = LPC_GPIO2;
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT3
 +  extObjectInit(&EXTD3);
 +  EXTD3.gpio = LPC_GPIO3;
 +#endif
 +}
 +
 +/**
 + * @brief   Configures and activates the EXT peripheral.
 + *
 + * @param[in] extp      pointer to the @p EXTDriver object
 + *
 + * @notapi
 + */
 +void ext_lld_start(EXTDriver *extp) {
 +  int i;
 +
 +  /* Configure all pins as edge sensitive */
 +#if LPC11xx_EXT_USE_EXT0
 +  if (extp == &EXTD0) {
 +    LPC_GPIO0->IS = 0;
 +    ext_lld_exti_irq_enable(EXTI0_IRQ);
 +  }
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT1
 +  if (extp == &EXTD1) {
 +    LPC_GPIO1->IS = 0;
 +    ext_lld_exti_irq_enable(EXTI1_IRQ);
 +  }
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT2
 +  if (extp == &EXTD2) {
 +    LPC_GPIO2->IS = 0;
 +    ext_lld_exti_irq_enable(EXTI2_IRQ);
 +  }
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT3
 +  if (extp == &EXTD3) {
 +    LPC_GPIO3->IS = 0;
 +    ext_lld_exti_irq_enable(EXTI3_IRQ);
 +  }
 +#endif
 +
 +  /* Configuration of autostart channels.*/
 +  for (i = 0; i < EXT_MAX_CHANNELS; i++)
 +    if (extp->config->channels[i].mode & EXT_CH_MODE_AUTOSTART)
 +      ext_lld_channel_enable(extp, i);
 +    else
 +      ext_lld_channel_disable(extp, i);
 +}
 +
 +/**
 + * @brief   Deactivates the EXT peripheral.
 + *
 + * @param[in] extp      pointer to the @p EXTDriver object
 + *
 + * @notapi
 + */
 +void ext_lld_stop(EXTDriver *extp) {
 +
 +  LPC_GPIO_TypeDef * gp = extp->gpio;
 +
 +  if (extp->state == EXT_ACTIVE) {
 +#if LPC11xx_EXT_USE_EXT0
 +    if (extp == &EXTD0) {
 +      ext_lld_exti_irq_disable(EXTI0_IRQ);
 +    }
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT1
 +    if (extp == &EXTD1) {
 +      ext_lld_exti_irq_disable(EXTI1_IRQ);
 +    }
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT2
 +    if (extp == &EXTD2) {
 +      ext_lld_exti_irq_disable(EXTI2_IRQ);
 +    }
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT3
 +    if (extp == &EXTD3) {
 +      ext_lld_exti_irq_disable(EXTI3_IRQ);
 +    }
 +#endif
 +  }
 +
 +  gp->IE = 0;
 +  gp->IC = 0xFFFFFFFF;
 +  __NOP();
 +  __NOP();
 +}
 +
 +/**
 + * @brief   Enables an EXT channel.
 + *
 + * @param[in] extp      pointer to the @p EXTDriver object
 + * @param[in] channel   channel to be enabled
 + *
 + * @notapi
 + */
 +void ext_lld_channel_enable(EXTDriver *extp, expchannel_t channel) {
 +
 +  LPC_GPIO_TypeDef * gp;
 +
 +  gp = extp->gpio;
 +  
 +  /* Programming edge irq enables */
 +  if (extp->config->channels[channel].mode & EXT_CH_MODE_BOTH_EDGES)
 +    gp->IBE |=  (1 << channel);
 +  else {
 +    gp->IBE &=  ~(1 << channel);
 +    if (extp->config->channels[channel].mode & EXT_CH_MODE_RISING_EDGE)
 +      gp->IEV |= (1 << channel);
 +    else
 +      gp->IEV &= (1 << channel);
 +  }
 +
 +  gp->IC = (1 << channel);    /* Clear interrupt on selected channel */
 +  __NOP();
 +  __NOP();
 +
 +  gp->IE |= (1 << channel);  /* Interrupt on selected channel
 +                                    is not masked */
 +}
 +
 +/**
 + * @brief   Disables an EXT channel.
 + *
 + * @param[in] extp      pointer to the @p EXTDriver object
 + * @param[in] channel   channel to be disabled
 + *
 + * @notapi
 + */
 +void ext_lld_channel_disable(EXTDriver *extp, expchannel_t channel) {
 +
 +  LPC_GPIO_TypeDef * gp;
 +
 +  gp = extp->gpio;
 +
 +  gp->IE &= ~(1 << channel);   /* Mask interrupt on selected channel */
 +  gp->IC = (1 << channel);      /* Clear interrupt on selected channel */
 +  __NOP();
 +  __NOP();
 +}
 +
 +#endif /* HAL_USE_EXT */
 +
 +/** @} */
 diff --git a/os/hal/platforms/LPC11xx/ext_lld.h b/os/hal/platforms/LPC11xx/ext_lld.h new file mode 100644 index 000000000..9a05f6d22 --- /dev/null +++ b/os/hal/platforms/LPC11xx/ext_lld.h @@ -0,0 +1,185 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
 +    LPC11xx EXT driver - Copyright (C) 2013 Marcin Jokel
 +                       - Copyright (C) 2013 mike brown
 +
 +    Licensed under the Apache License, Version 2.0 (the "License");
 +    you may not use this file except in compliance with the License.
 +    You may obtain a copy of the License at
 +
 +        http://www.apache.org/licenses/LICENSE-2.0
 +
 +    Unless required by applicable law or agreed to in writing, software
 +    distributed under the License is distributed on an "AS IS" BASIS,
 +    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 +    See the License for the specific language governing permissions and
 +    limitations under the License.
 +*/
 +
 +/**
 + * @file    LPC11xx/ext_lld.h
 + * @brief   LPC11xx EXT subsystem low level driver header.
 + *
 + * @addtogroup EXT
 + * @{
 + */
 +
 +#ifndef _EXT_LLD_H_
 +#define _EXT_LLD_H_
 +
 +#if HAL_USE_EXT || defined(__DOXYGEN__)
 +
 +/*===========================================================================*/
 +/* Driver constants.                                                         */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   Available number of EXT channels.
 + */
 +#define EXT_MAX_CHANNELS    12
 +
 +
 +/*===========================================================================*/
 +/* Driver pre-compile time settings.                                         */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   EXT0 driver enable switch.
 + * @details If set to @p TRUE the support for EXT0 is included.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_EXT_USE_EXT0) || defined(__DOXYGEN__)
 +#define LPC11xx_EXT_USE_EXT0              FALSE
 +#endif
 +
 +/**
 + * @brief   EXT1 driver enable switch.
 + * @details If set to @p TRUE the support for EXT1 is included.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_EXT_USE_EXT1) || defined(__DOXYGEN__)
 +#define LPC11xx_EXT_USE_EXT1              FALSE
 +#endif
 +
 +/**
 + * @brief   EXT2 driver enable switch.
 + * @details If set to @p TRUE the support for EXT2 is included.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_EXT_USE_EXT2) || defined(__DOXYGEN__)
 +#define LPC11xx_EXT_USE_EXT2              FALSE
 +#endif
 +
 +/**
 + * @brief   EXT3 driver enable switch.
 + * @details If set to @p TRUE the support for EXT3 is included.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_EXT_USE_EXT3) || defined(__DOXYGEN__)
 +#define LPC11xx_EXT_USE_EXT3              FALSE
 +#endif
 +/*===========================================================================*/
 +/* Derived constants and error checks.                                       */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver data structures and types.                                         */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   EXT channel identifier.
 + */
 +typedef uint32_t expchannel_t;
 +
 +/**
 + * @brief   Type of an EXT generic notification callback.
 + *
 + * @param[in] extp      pointer to the @p EXPDriver object triggering the
 + *                      callback
 + */
 +typedef void (*extcallback_t)(EXTDriver *extp, expchannel_t channel);
 +
 +/**
 + * @brief   Channel configuration structure.
 + */
 +typedef struct {
 +  /**
 +   * @brief Channel mode.
 +   */
 +  uint8_t               mode;
 +
 +  /**
 +   * @brief Channel callback.
 +   */
 +  extcallback_t         cb;
 +} EXTChannelConfig;
 +
 +/**
 + * @brief   Driver configuration structure.
 + * @note    It could be empty on some architectures.
 + */
 +typedef struct {
 +  /**
 +   * @brief Channel configurations.
 +   */
 +  EXTChannelConfig      channels[EXT_MAX_CHANNELS];
 +  /* End of the mandatory fields.*/
 +} EXTConfig;
 +
 +/**
 + * @brief   Structure representing an EXT driver.
 + */
 +struct EXTDriver {
 +  /**
 +   * @brief Driver state.
 +   */
 +  extstate_t                state;
 +  /**
 +   * @brief Current configuration data.
 +   */
 +  const EXTConfig           *config;
 +  /* End of the mandatory fields.*/
 +  LPC_GPIO_TypeDef          *gpio;
 +};
 +
 +/*===========================================================================*/
 +/* Driver macros.                                                            */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* External declarations.                                                    */
 +/*===========================================================================*/
 +
 +#if LPC11xx_EXT_USE_EXT0 || !defined(__DOXYGEN__)
 +extern EXTDriver EXTD0;
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT1 || !defined(__DOXYGEN__)
 +extern EXTDriver EXTD1;
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT2 || !defined(__DOXYGEN__)
 +extern EXTDriver EXTD2;
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT3 || !defined(__DOXYGEN__)
 +extern EXTDriver EXTD3;
 +#endif
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +  void ext_lld_init(void);
 +  void ext_lld_start(EXTDriver *extp);
 +  void ext_lld_stop(EXTDriver *extp);
 +  void ext_lld_channel_enable(EXTDriver *extp, expchannel_t channel);
 +  void ext_lld_channel_disable(EXTDriver *extp, expchannel_t channel);
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#endif /* HAL_USE_EXT */
 +
 +#endif /* _EXT_LLD_H_ */
 +
 +/** @} */
 diff --git a/os/hal/platforms/LPC11xx/ext_lld_isr.c b/os/hal/platforms/LPC11xx/ext_lld_isr.c new file mode 100644 index 000000000..9d3b92eeb --- /dev/null +++ b/os/hal/platforms/LPC11xx/ext_lld_isr.c @@ -0,0 +1,176 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
 +    LPC11xx EXT driver - Copyright (C) 2013 Marcin Jokel
 +
 +    Licensed under the Apache License, Version 2.0 (the "License");
 +    you may not use this file except in compliance with the License.
 +    You may obtain a copy of the License at
 +
 +        http://www.apache.org/licenses/LICENSE-2.0
 +
 +    Unless required by applicable law or agreed to in writing, software
 +    distributed under the License is distributed on an "AS IS" BASIS,
 +    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 +    See the License for the specific language governing permissions and
 +    limitations under the License.
 +*/
 +
 +/**
 + * @file    LPC11xx/ext_lld_isr.c
 + * @brief   LPC11xx EXT subsystem low level driver ISR code.
 + *
 + * @addtogroup EXT
 + * @{
 + */
 +
 +#include "ch.h"
 +#include "hal.h"
 +
 +#if HAL_USE_EXT || defined(__DOXYGEN__)
 +
 +#include "ext_lld_isr.h"
 +
 +/*===========================================================================*/
 +/* Driver local definitions.                                                 */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver exported variables.                                                */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver local variables and types.                                         */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver local functions.                                                   */
 +/*===========================================================================*/
 +
 +#if LPC11xx_EXT_USE_EXT0 || LPC11xx_EXT_USE_EXT1 || LPC11xx_EXT_USE_EXT2 ||   \
 +  LPC11xx_EXT_USE_EXT3 || defined(__DOXYGEN__)
 +/**
 + * @brief   I2C error handler.
 + *
 + * @param[in] i2cp      pointer to the @p I2CDriver object
 + *
 + * @notapi
 + */
 +static void ext_lld_serve_interrupt(EXTDriver *extp) {
 +  uint32_t port_stat;
 +  uint8_t i;
 +
 +  port_stat = extp->gpio->MIS;   /* Read interrupt status */
 +  extp->gpio->IC = port_stat;    /* Clear interrupt flags */
 +
 +  for (i = 0; i < EXT_MAX_CHANNELS; i++) {
 +    if (port_stat & 0x01) {
 +      extp->config->channels[i].cb(extp, i);
 +    }
 +    port_stat  = port_stat >> 1;
 +  }
 +}
 +#endif
 +/*===========================================================================*/
 +/* Driver interrupt handlers.                                                */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   PIO0 interrupt handler.
 + *
 + * @isr
 + */
 +#if LPC11xx_EXT_USE_EXT0 || defined(__DOXYGEN__)
 +CH_IRQ_HANDLER(VectorBC) {
 +
 +  CH_IRQ_PROLOGUE();
 +  ext_lld_serve_interrupt(&EXTD0);
 +  CH_IRQ_EPILOGUE();
 +}
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT1 || defined(__DOXYGEN__)
 +/**
 + * @brief   PIO1 interrupt handler.
 + *
 + * @isr
 + */
 +CH_IRQ_HANDLER(VectorB8) {
 +
 +  CH_IRQ_PROLOGUE();
 +  ext_lld_serve_interrupt(&EXTD1);
 +  CH_IRQ_EPILOGUE();
 +}
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT2 || defined(__DOXYGEN__)
 +/**
 + * @brief   PIO2 interrupt handler.
 + *
 + * @isr
 + */
 +CH_IRQ_HANDLER(VectorB4) {
 +
 +  CH_IRQ_PROLOGUE();
 +  ext_lld_serve_interrupt(&EXTD2);
 +  CH_IRQ_EPILOGUE();
 +}
 +#endif
 +
 +#if LPC11xx_EXT_USE_EXT3 || defined(__DOXYGEN__)
 +/**
 + * @brief   PIO_3 interrupt handler.
 + *
 + * @isr
 + */
 +CH_IRQ_HANDLER(VectorB0) {
 +
 +  CH_IRQ_PROLOGUE();
 +  ext_lld_serve_interrupt(&EXTD3);
 +  CH_IRQ_EPILOGUE();
 +}
 +#endif
 +
 +/*===========================================================================*/
 +/* Driver exported functions.                                                */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   Enables EXTI IRQ sources.
 + *
 + * @notapi
 + */
 +void ext_lld_exti_irq_enable(extirq_t irqn) {
 +
 +  uint32_t pmask;
 +
 +  switch (irqn) {
 +  case EXTI0_IRQ:
 +    pmask = LPC11xx_EXT_EXTI0_IRQ_PRIORITY;
 +    break;
 +  case EXTI1_IRQ:
 +    pmask = LPC11xx_EXT_EXTI1_IRQ_PRIORITY;
 +    break;
 +  case EXTI2_IRQ:
 +    pmask = LPC11xx_EXT_EXTI2_IRQ_PRIORITY;
 +    break;
 +  case EXTI3_IRQ:
 +    pmask = LPC11xx_EXT_EXTI3_IRQ_PRIORITY;
 +    break;
 +  }
 +  nvicEnableVector(EINT0_IRQn - irqn, CORTEX_PRIORITY_MASK(pmask));
 +
 +}
 +
 +/**
 + * @brief   Disables EXTI IRQ sources.
 + *
 + * @notapi
 + */
 +void ext_lld_exti_irq_disable(extirq_t irqn) {
 +
 +  nvicDisableVector(EINT0_IRQn - irqn);
 +}
 +
 +#endif /* HAL_USE_EXT */
 +
 +/** @} */
 diff --git a/os/hal/platforms/LPC11xx/ext_lld_isr.h b/os/hal/platforms/LPC11xx/ext_lld_isr.h new file mode 100644 index 000000000..442d109da --- /dev/null +++ b/os/hal/platforms/LPC11xx/ext_lld_isr.h @@ -0,0 +1,111 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
 +    LPC11xx EXT driver - Copyright (C) 2013 Marcin Jokel
 +
 +    Licensed under the Apache License, Version 2.0 (the "License");
 +    you may not use this file except in compliance with the License.
 +    You may obtain a copy of the License at
 +
 +        http://www.apache.org/licenses/LICENSE-2.0
 +
 +    Unless required by applicable law or agreed to in writing, software
 +    distributed under the License is distributed on an "AS IS" BASIS,
 +    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 +    See the License for the specific language governing permissions and
 +    limitations under the License.
 +*/
 +
 +/**
 + * @file    LPC11xx/ext_lld_isr.h
 + * @brief   LPC11xx EXT subsystem low level driver ISR header.
 + *
 + * @addtogroup EXT
 + * @{
 + */
 +
 +#ifndef _EXT_LLD_ISR_H_
 +#define _EXT_LLD_ISR_H_
 +
 +#if HAL_USE_EXT || defined(__DOXYGEN__)
 +
 +/*===========================================================================*/
 +/* Driver constants.                                                         */
 +/*===========================================================================*/
 +
 +#define EXTI0_IRQ           0
 +#define EXTI1_IRQ           1
 +#define EXTI2_IRQ           2
 +#define EXTI3_IRQ           3
 +
 +/*===========================================================================*/
 +/* Driver pre-compile time settings.                                         */
 +/*===========================================================================*/
 +
 +/**
 + * @name    Configuration options
 + * @{
 + */
 +/**
 + * @brief   EXTI0 interrupt priority level setting.
 + */
 +#if !defined(LPC11xx_EXT_EXTI0_IRQ_PRIORITY) || defined(__DOXYGEN__)
 +#define LPC11xx_EXT_EXTI0_IRQ_PRIORITY      3
 +#endif
 +
 +/**
 + * @brief   EXTI1 interrupt priority level setting.
 + */
 +#if !defined(LPC11xx_EXT_EXTI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
 +#define LPC11xx_EXT_EXTI1_IRQ_PRIORITY      3
 +#endif
 +
 +/**
 + * @brief   EXTI2 interrupt priority level setting.
 + */
 +#if !defined(LPC11xx_EXT_EXTI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
 +#define LPC11xx_EXT_EXTI2_IRQ_PRIORITY      3
 +#endif
 +
 +/**
 + * @brief   EXTI3 interrupt priority level setting.
 + */
 +#if !defined(LPC11xx_EXT_EXTI3_IRQ_PRIORITY) || defined(__DOXYGEN__)
 +#define LPC11xx_EXT_EXTI3_IRQ_PRIORITY      3
 +#endif
 +
 +/** @} */
 +
 +/*===========================================================================*/
 +/* Derived constants and error checks.                                       */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver data structures and types.                                         */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   EXT irq port identifier.
 + */
 +typedef uint32_t extirq_t;
 +/*===========================================================================*/
 +/* Driver macros.                                                            */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* External declarations.                                                    */
 +/*===========================================================================*/
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +  void ext_lld_exti_irq_enable(extirq_t irqn);
 +  void ext_lld_exti_irq_disable(extirq_t irqn);
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#endif /* HAL_USE_EXT */
 +
 +#endif /* _EXT_LLD_ISR_H_ */
 +
 +/** @} */
 diff --git a/os/hal/platforms/LPC11xx/i2c_lld.c b/os/hal/platforms/LPC11xx/i2c_lld.c new file mode 100644 index 000000000..c68f11460 --- /dev/null +++ b/os/hal/platforms/LPC11xx/i2c_lld.c @@ -0,0 +1,438 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
 +    LPC11xx I2C driver - Copyright (C) 2013 Marcin Jokel
 +
 +    Licensed under the Apache License, Version 2.0 (the "License");
 +    you may not use this file except in compliance with the License.
 +    You may obtain a copy of the License at
 +
 +        http://www.apache.org/licenses/LICENSE-2.0
 +
 +    Unless required by applicable law or agreed to in writing, software
 +    distributed under the License is distributed on an "AS IS" BASIS,
 +    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 +    See the License for the specific language governing permissions and
 +    limitations under the License.
 +*/
 +
 +/*
 +   Concepts and parts of this file have been contributed by Uladzimir Pylinsky
 +   aka barthess.
 + */
 +
 +
 +/**
 + * @file    LPC11xx/i2c_lld.h
 + * @brief   LPC11xx I2C subsystem low level driver header.
 + *
 + * @addtogroup I2C
 + * @{
 + */
 +
 +#include "ch.h"
 +#include "hal.h"
 +
 +#if HAL_USE_I2C || defined(__DOXYGEN__)
 +
 +/*===========================================================================*/
 +/* Driver local definitions.                                                 */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver constants.                                                         */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver exported variables.                                                */
 +/*===========================================================================*/
 +
 +/** @brief I2C1 driver identifier.*/
 +I2CDriver I2CD1;
 +
 +/*===========================================================================*/
 +/* Driver local variables.                                                   */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver local functions.                                                   */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   Wakes up the waiting thread.
 + *
 + * @param[in] i2cp      pointer to the @p I2CDriver object
 + * @param[in] msg       wakeup message
 + *
 + * @notapi
 + */
 +#define wakeup_isr(i2cp, msg) {                                             \
 +  chSysLockFromIsr();                                                       \
 +  if ((i2cp)->thread != NULL) {                                             \
 +    Thread *tp = (i2cp)->thread;                                            \
 +    (i2cp)->thread = NULL;                                                  \
 +    tp->p_u.rdymsg = (msg);                                                 \
 +    chSchReadyI(tp);                                                        \
 +  }                                                                         \
 +  chSysUnlockFromIsr();                                                     \
 +}
 +
 +/**
 + * @brief   Handling of stalled I2C transactions.
 + *
 + * @param[in] i2cp      pointer to the @p I2CDriver object
 + *
 + * @notapi
 + */
 +static void i2c_lld_safety_timeout(void *p) {
 +  I2CDriver *i2cp = (I2CDriver *)p;
 +
 +  chSysLockFromIsr();
 +  if (i2cp->thread) {
 +    Thread *tp = i2cp->thread;
 +    i2cp->thread = NULL;
 +    tp->p_u.rdymsg = RDY_TIMEOUT;
 +    chSchReadyI(tp);
 +  }
 +  chSysUnlockFromIsr();
 +}
 +
 +/**
 + * @brief   I2C error handler.
 + *
 + * @param[in] i2cp      pointer to the @p I2CDriver object
 + *
 + * @notapi
 + */
 +static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t status) {
 +  i2cflags_t error = 0;
 +
 +  switch (status) {
 +    case I2C_STATE_ARB_LOST:
 +      error = I2CD_ARBITRATION_LOST;
 +      break;
 +    case I2C_STATE_BUS_ERROR:
 +      error = I2CD_BUS_ERROR;
 +      break;
 +    case I2C_STATE_MS_SLAR_NACK:
 +    case I2C_STATE_MS_TDAT_NACK:
 +    case I2C_STATE_MS_SLAW_NACK:
 +      error = I2CD_ACK_FAILURE ;
 +      break;
 +  }
 +
 +  /* If some error has been identified then sends wakes the waiting thread.*/
 +  i2cp->errors = error;
 +  wakeup_isr(i2cp, RDY_RESET);
 +}
 +
 +/*===========================================================================*/
 +/* Driver interrupt handlers.                                                */
 +/*===========================================================================*/
 +/**
 + * @brief   I2C event interrupt handler.
 + *
 + * @notapi
 + */
 +CH_IRQ_HANDLER(Vector7C) {
 +  uint32_t status;
 +
 +  CH_IRQ_PROLOGUE();
 +  status = LPC_I2C->STAT;
 +  switch(status) {
 +    case I2C_STATE_MS_START:    /*  A START condition has been transmitted. */
 +      if (I2CD1.txbytes > 0) {
 +        LPC_I2C->DAT = I2CD1.addr;                  /* Write slave address with WR bit. */
 +      }
 +      else {
 +        LPC_I2C->DAT = I2CD1.addr | I2C_RD_BIT;     /* Write slave address with RD bit. */
 +      }
 +
 +      LPC_I2C->CONCLR = I2C_CONCLR_STAC | I2C_CONCLR_SIC;   /* Clear START and SI bit. */
 +      break;
 +
 +    case I2C_STATE_MS_SLAR_NACK: /* NOT ACK has been received, Master will be transmitted STOP. */
 +    case I2C_STATE_MS_TDAT_NACK: /* NOT ACK has been received, Master will be transmitted STOP. */
 +    case I2C_STATE_MS_SLAW_NACK: /* NOT ACK has been received, Master will be transmitted STOP. */
 +      LPC_I2C->CONSET = I2C_CONSET_STO;             /* Set STOP bit. */
 +      LPC_I2C->CONCLR = I2C_CONCLR_SIC;             /* Clear SI bit. */
 +      i2c_lld_serve_error_interrupt(&I2CD1, status);
 +      break;
 +
 +    case I2C_STATE_MS_SLAW_ACK: /* SLA + W has been transmitted, ACK has been received. */
 +    case I2C_STATE_MS_TDAT_ACK: /* Data byte has been transmitted, ACK has been received. */
 +      if (I2CD1.txbytes > 0) {
 +        LPC_I2C->DAT = *I2CD1.txbuf++;               /* Write data. */
 +        I2CD1.txbytes--;
 +      }
 +      else {
 +        if (I2CD1.rxbytes > 0) {
 +          LPC_I2C->CONSET = I2C_CONSET_STO | I2C_CONSET_STA; /* Set START and STOP bit. */
 +        }                                                    /* STOP bit will be transmit, then START bit. */
 +        else {
 +          LPC_I2C->CONSET = I2C_CONSET_STO;         /* Set STOP bit. */
 +          wakeup_isr(&I2CD1, RDY_OK);
 +        }
 +      }
 +      LPC_I2C->CONCLR = I2C_CONCLR_SIC;             /* Clear SI bit. */
 +      break;
 +
 +    case I2C_STATE_MS_SLAR_ACK: /* SLA + R has been transmitted, ACK has been received. */
 +    case I2C_STATE_MS_RDAT_ACK: /* Data byte has been received, ACK has been returned. */
 +      if (status == I2C_STATE_MS_RDAT_ACK) {
 +        *I2CD1.rxbuf++ = LPC_I2C->DAT;                /* Read data */
 +        I2CD1.rxbytes--;
 +      }
 +      if (I2CD1.rxbytes == 1) {
 +        LPC_I2C->CONCLR = I2C_CONCLR_SIC | I2C_CONCLR_AAC; /* Clear SI and ACK bit. */
 +      }
 +      else {
 +        LPC_I2C->CONSET = I2C_CONSET_AA;            /* Set ACK bit. */
 +        LPC_I2C->CONCLR = I2C_CONCLR_SIC;           /* Clear SI bit. */
 +      }
 +      break;
 +
 +    case I2C_STATE_MS_RDAT_NACK: /* Data byte has been received, NOT ACK has been returned. */
 +      *I2CD1.rxbuf++ = LPC_I2C->DAT;                /* Read data. */
 +      I2CD1.rxbytes--;
 +      LPC_I2C->CONSET = I2C_CONSET_STO;             /* Set STOP bit. */
 +      LPC_I2C->CONCLR = I2C_CONCLR_SIC;             /* Clear SI bit. */
 +      wakeup_isr(&I2CD1, RDY_OK);
 +      break;
 +
 +    case I2C_STATE_BUS_ERROR: /* Bus error. */
 +    case I2C_STATE_ARB_LOST:  /* Arbitration lost. */
 +      LPC_I2C->CONCLR = I2C_CONCLR_SIC;             /* Clear SI bit. */
 +      i2c_lld_serve_error_interrupt(&I2CD1, status);
 +      break;
 +
 +  }
 +
 +  CH_IRQ_EPILOGUE();
 +}
 +
 +/*===========================================================================*/
 +/* Driver exported functions.                                                */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   Low level I2C driver initialization.
 + *
 + * @notapi
 + */
 +void i2c_lld_init(void) {
 +
 +  i2cObjectInit(&I2CD1);
 +  I2CD1.thread = NULL;
 +  I2CD1.i2c    = LPC_I2C;
 +
 +  LPC_IOCON->PIO0_4 = 0x01;  /* Set I2C SCL pin function */
 +  LPC_IOCON->PIO0_5 = 0x01;  /* Set I2C SDA pin function */
 +}
 +
 +/**
 + * @brief   Configures and activates the I2C peripheral.
 + *
 + * @param[in] i2cp      pointer to the @p I2CDriver object
 + *
 + * @notapi
 + */
 +void i2c_lld_start(I2CDriver *i2cp) {
 +  uint32_t i2cscl;
 +  uint32_t mulh, mull, div;
 +  LPC_I2C_TypeDef *dp = i2cp->i2c;
 +
 +  /* Make sure I2C peripheral is disabled */
 +  dp->CONCLR = I2C_CONCLR_ENC;
 +
 +  /* If in stopped state then enables the I2C clock. */
 +  if (i2cp->state == I2C_STOP) {
 +
 +  if (&I2CD1 == i2cp) {
 +    LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 5); /* Enable clock. */
 +    LPC_SYSCON->PRESETCTRL &= ~(1 << 1);   /* Reset I2C peripheral.*/
 +    __NOP();
 +    LPC_SYSCON->PRESETCTRL |= (1 << 1);
 +    nvicEnableVector(I2C_IRQn,
 +          CORTEX_PRIORITY_MASK(LPC11xx_I2C_IRQ_PRIORITY));
 +  }
 +
 +  }
 +
 +  /* Setup I2C clock parameters.*/
 +  i2cscl = (LPC11xx_SYSCLK/(i2cp->config->clock_timing));
 +  if (i2cp->config->mode == I2C_FAST_MODE) {
 +    div = 19;
 +    mull = 13;
 +    mulh = 6;
 +  } else if (i2cp->config->mode == I2C_FAST_MODE_PLUS) {
 +    div = 3;
 +    mull = 2;
 +    mulh = 1;
 +  } else { /* i2cp->config->mode == I2C_STANDARD_MODE */
 +    div = 2;
 +    mull = 1;
 +    mulh = 1;
 +  }
 +
 +  dp->SCLH = (mulh * i2cscl) / div;
 +  dp->SCLL = (mull * i2cscl) / div;
 +
 +  /* Enable I2C.*/
 +  dp->CONSET |= I2C_CONSET_EN;
 +}
 +
 +/**
 + * @brief   Deactivates the I2C peripheral.
 + *
 + * @param[in] i2cp      pointer to the @p I2CDriver object
 + *
 + * @notapi
 + */
 +void i2c_lld_stop(I2CDriver *i2cp) {
 +
 +  /* If not in stopped state then disables the I2C clock.*/
 +  if (i2cp->state != I2C_STOP) {
 +
 +    /* I2C disable.*/
 +    i2cp->i2c->CONCLR = I2C_CONCLR_ENC;
 +
 +    if (&I2CD1 == i2cp) {
 +      nvicDisableVector(I2C_IRQn);
 +      LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 5);
 +    }
 +  }
 +}
 +
 +/**
 + * @brief   Receives data via the I2C bus as master.
 + * @details Number of receiving bytes must be more than 1 on STM32F1x. This is
 + *          hardware restriction.
 + *
 + * @param[in] i2cp      pointer to the @p I2CDriver object
 + * @param[in] addr      slave device address
 + * @param[out] rxbuf    pointer to the receive buffer
 + * @param[in] rxbytes   number of bytes to be received
 + * @param[in] timeout   the number of ticks before the operation timeouts,
 + *                      the following special values are allowed:
 + *                      - @a TIME_INFINITE no timeout.
 + *                      .
 + * @return              The operation status.
 + * @retval RDY_OK       if the function succeeded.
 + * @retval RDY_RESET    if one or more I2C errors occurred, the errors can
 + *                      be retrieved using @p i2cGetErrors().
 + * @retval RDY_TIMEOUT  if a timeout occurred before operation end. <b>After a
 + *                      timeout the driver must be stopped and restarted
 + *                      because the bus is in an uncertain state</b>.
 + *
 + * @notapi
 + */
 +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
 +                                     uint8_t *rxbuf, size_t rxbytes,
 +                                     systime_t timeout) {
 +  LPC_I2C_TypeDef *dp = i2cp->i2c;
 +  VirtualTimer vt;
 +
 +  i2cp->addr = addr << 1;
 +  /* Global timeout for the whole operation.*/
 +  if (timeout != TIME_INFINITE)
 +    chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp);
 +
 +  /* Releases the lock from high level driver.*/
 +  chSysUnlock();
 +
 +  /* Initializes driver fields */
 +  i2cp->errors = 0;
 +  i2cp->rxbuf = rxbuf;
 +  i2cp->rxbytes = rxbytes;
 +
 +  /* This lock will be released in high level driver.*/
 +  chSysLock();
 +
 +  /* Atomic check on the timer in order to make sure that a timeout didn't
 +     happen outside the critical zone.*/
 +  if ((timeout != TIME_INFINITE) && !chVTIsArmedI(&vt))
 +    return RDY_TIMEOUT;
 +
 +  /* Starts the operation.*/
 +  dp->CONSET = I2C_CONSET_STA;
 +
 +  /* Waits for the operation completion or a timeout.*/
 +  i2cp->thread = chThdSelf();
 +  chSchGoSleepS(THD_STATE_SUSPENDED);
 +  if ((timeout != TIME_INFINITE) && chVTIsArmedI(&vt))
 +    chVTResetI(&vt);
 +
 +  return chThdSelf()->p_u.rdymsg;
 +}
 +
 +/**
 + * @brief   Transmits data via the I2C bus as master.
 + * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x.
 + *          This is hardware restriction.
 + *
 + * @param[in] i2cp      pointer to the @p I2CDriver object
 + * @param[in] addr      slave device address
 + * @param[in] txbuf     pointer to the transmit buffer
 + * @param[in] txbytes   number of bytes to be transmitted
 + * @param[out] rxbuf    pointer to the receive buffer
 + * @param[in] rxbytes   number of bytes to be received
 + * @param[in] timeout   the number of ticks before the operation timeouts,
 + *                      the following special values are allowed:
 + *                      - @a TIME_INFINITE no timeout.
 + *                      .
 + * @return              The operation status.
 + * @retval RDY_OK       if the function succeeded.
 + * @retval RDY_RESET    if one or more I2C errors occurred, the errors can
 + *                      be retrieved using @p i2cGetErrors().
 + * @retval RDY_TIMEOUT  if a timeout occurred before operation end. <b>After a
 + *                      timeout the driver must be stopped and restarted
 + *                      because the bus is in an uncertain state</b>.
 + *
 + * @notapi
 + */
 +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
 +                                      const uint8_t *txbuf, size_t txbytes,
 +                                      uint8_t *rxbuf, size_t rxbytes,
 +                                      systime_t timeout) {
 +  LPC_I2C_TypeDef *dp = i2cp->i2c;
 +  VirtualTimer vt;
 +
 +  i2cp->addr = addr << 1;
 +  /* Global timeout for the whole operation.*/
 +  if (timeout != TIME_INFINITE)
 +    chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp);
 +
 +  /* Releases the lock from high level driver.*/
 +  chSysUnlock();
 +
 +  /* Initializes driver fields */
 +  i2cp->errors = 0;
 +  i2cp->txbuf = txbuf;
 +  i2cp->txbytes = txbytes;
 +  i2cp->rxbuf = rxbuf;
 +  i2cp->rxbytes = rxbytes;
 +
 +  /* This lock will be released in high level driver.*/
 +  chSysLock();
 +
 +  /* Atomic check on the timer in order to make sure that a timeout didn't
 +     happen outside the critical zone.*/
 +  if ((timeout != TIME_INFINITE) && !chVTIsArmedI(&vt))
 +    return RDY_TIMEOUT;
 +
 +  /* Starts the operation.*/
 +  dp->CONSET = I2C_CONSET_STA;
 +
 +  /* Waits for the operation completion or a timeout.*/
 +  i2cp->thread = chThdSelf();
 +  chSchGoSleepS(THD_STATE_SUSPENDED);
 +
 +  if ((timeout != TIME_INFINITE) && chVTIsArmedI(&vt))
 +    chVTResetI(&vt);
 +
 +  return chThdSelf()->p_u.rdymsg;
 +}
 +
 +#endif /* HAL_USE_I2C */
 +
 +/** @} */
 diff --git a/os/hal/platforms/LPC11xx/i2c_lld.h b/os/hal/platforms/LPC11xx/i2c_lld.h new file mode 100644 index 000000000..b908ba6e4 --- /dev/null +++ b/os/hal/platforms/LPC11xx/i2c_lld.h @@ -0,0 +1,225 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
 +    LPC11xx I2C driver - Copyright (C) 2013 Marcin Jokel
 +
 +    Licensed under the Apache License, Version 2.0 (the "License");
 +    you may not use this file except in compliance with the License.
 +    You may obtain a copy of the License at
 +
 +        http://www.apache.org/licenses/LICENSE-2.0
 +
 +    Unless required by applicable law or agreed to in writing, software
 +    distributed under the License is distributed on an "AS IS" BASIS,
 +    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 +    See the License for the specific language governing permissions and
 +    limitations under the License.
 +*/
 +/*
 +   Concepts and parts of this file have been contributed by Uladzimir Pylinsky
 +   aka barthess.
 + */
 +
 +/**
 + * @file    LPC11xx/i2c_lld.h
 + * @brief   LPC11xx I2C subsystem low level driver header.
 + *
 + * @addtogroup I2C
 + * @{
 + */
 +
 +#ifndef _I2C_LLD_H_
 +#define _I2C_LLD_H_
 +
 +#if HAL_USE_I2C || defined(__DOXYGEN__)
 +
 +/*===========================================================================*/
 +/* Driver constants.                                                         */
 +/*===========================================================================*/
 +
 +#define I2C_CONSET_AA               0x04  /* Assert acknowledge flag. */
 +#define I2C_CONSET_SI               0x08  /* I2C interrupt flag. */
 +#define I2C_CONSET_STO              0x10  /* STOP flag. */
 +#define I2C_CONSET_STA              0x20  /* START flag. */
 +#define I2C_CONSET_EN               0x40  /* I2C interface enable. */
 +
 +#define I2C_CONCLR_AAC              0x04  /* Assert acknowledge Clear bit. */
 +#define I2C_CONCLR_SIC              0x08  /* I2C interrupt Clear bit. */
 +#define I2C_CONCLR_STAC             0x20  /* START flag Clear bit. */
 +#define I2C_CONCLR_ENC              0x40  /* I2C interface Disable bit. */
 +
 +#define I2C_WR_BIT                  0x00
 +#define I2C_RD_BIT                  0x01
 +
 +#define I2C_STATE_MS_START          0x08
 +#define I2C_STATE_MS_RSTART         0x10
 +#define I2C_STATE_MS_SLAW_ACK       0x18
 +#define I2C_STATE_MS_SLAW_NACK      0x20
 +#define I2C_STATE_MS_TDAT_ACK       0x28
 +#define I2C_STATE_MS_TDAT_NACK      0x30
 +#define I2C_STATE_ARB_LOST          0x38
 +
 +#define I2C_STATE_MS_SLAR_ACK       0x40
 +#define I2C_STATE_MS_SLAR_NACK      0x48
 +#define I2C_STATE_MS_RDAT_ACK       0x50
 +#define I2C_STATE_MS_RDAT_NACK      0x58
 +
 +#define I2C_STATE_BUS_ERROR         0x00
 +
 +/*===========================================================================*/
 +/* Driver pre-compile time settings.                                         */
 +/*===========================================================================*/
 +/**
 + * @name    Configuration options
 + * @{
 + */
 +
 +/**
 + * @brief   I2C1 interrupt priority level setting.
 + */
 +#if !defined(LPC11xx_I2C_IRQ_PRIORITY) || defined(__DOXYGEN__)
 +#define LPC11xx_I2C_IRQ_PRIORITY     3
 +#endif
 +
 +/** @} */
 +
 +/*===========================================================================*/
 +/* Derived constants and error checks.                                       */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver data structures and types.                                         */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   Type representing I2C address.
 + */
 +typedef uint16_t i2caddr_t;
 +
 +/**
 + * @brief   I2C Driver condition flags type.
 + */
 +typedef uint32_t i2cflags_t;
 +/**
 + * @brief   Supported modes for the I2C bus.
 + */
 +typedef enum {
 +  I2C_STANDARD_MODE = 1,
 +  I2C_FAST_MODE = 2,
 +  I2C_FAST_MODE_PLUS = 3,
 +} i2cmode_t;
 +
 +/**
 + * @brief Driver configuration structure.
 + */
 +typedef struct {
 +  i2cmode_t       mode;             /**< @brief Specifies the I2C mode.        */
 +  uint32_t        clock_timing;     /**< @brief Specifies the clock timing     */
 +} I2CConfig;
 +
 +/**
 + * @brief   Type of a structure representing an I2C driver.
 + */
 +typedef struct I2CDriver I2CDriver;
 +
 +/**
 + * @brief Structure representing an I2C driver.
 + */
 +struct I2CDriver {
 +  /**
 +   * @brief   Driver state.
 +   */
 +  i2cstate_t                state;
 +  /**
 +   * @brief   Current configuration data.
 +   */
 +  const I2CConfig           *config;
 +  /**
 +   * @brief   Error flags.
 +   */
 +  i2cflags_t                errors;
 +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
 +#if CH_USE_MUTEXES || defined(__DOXYGEN__)
 +  /**
 +   * @brief   Mutex protecting the bus.
 +   */
 +  Mutex                     mutex;
 +#elif CH_USE_SEMAPHORES
 +  Semaphore                 semaphore;
 +#endif
 +#endif /* I2C_USE_MUTUAL_EXCLUSION */
 +#if defined(I2C_DRIVER_EXT_FIELDS)
 +  I2C_DRIVER_EXT_FIELDS
 +#endif
 +  /* End of the mandatory fields.*/
 +  /**
 +   * @brief   Thread waiting for I/O completion.
 +   */
 +  Thread                    *thread;
 +  /**
 +   * @brief     Current slave address without R/W bit.
 +   */
 +  i2caddr_t                 addr;
 +  /**
 +   * @brief     Pointer to the transmit buffer.
 +   */
 +  const uint8_t             *txbuf;
 +  /**
 +    * @brief    Number of bytes to transmit.
 +    */
 +  size_t                    txbytes;
 +  /**
 +    * @brief     Pointer to the receive buffer.
 +    */
 +  uint8_t                   *rxbuf;
 +  /**
 +      * @brief    Number of bytes to receive.
 +      */
 +  size_t                    rxbytes;
 +  /**
 +   * @brief     Pointer to the I2C registers block.
 +   */
 +  LPC_I2C_TypeDef           *i2c;
 +};
 +
 +/*===========================================================================*/
 +/* Driver macros.                                                            */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   Get errors from I2C driver.
 + *
 + * @param[in] i2cp      pointer to the @p I2CDriver object
 + *
 + * @notapi
 + */
 +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
 +
 +/*===========================================================================*/
 +/* External declarations.                                                    */
 +/*===========================================================================*/
 +
 +#if !defined(__DOXYGEN__)
 +extern I2CDriver I2CD1;
 +#endif
 +
 +#endif /* !defined(__DOXYGEN__) */
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +  void i2c_lld_init(void);
 +  void i2c_lld_start(I2CDriver *i2cp);
 +  void i2c_lld_stop(I2CDriver *i2cp);
 +  msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
 +                                        const uint8_t *txbuf, size_t txbytes,
 +                                        uint8_t *rxbuf, size_t rxbytes,
 +                                        systime_t timeout);
 +  msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
 +                                       uint8_t *rxbuf, size_t rxbytes,
 +                                       systime_t timeout);
 +#ifdef __cplusplus
 +}
 +#endif
 +#endif /* _I2C_LLD_H_ */
 +
 +/** @} */
 diff --git a/os/hal/platforms/LPC11xx/platform.mk b/os/hal/platforms/LPC11xx/platform.mk index 4f0d19547..61f2a49dd 100644 --- a/os/hal/platforms/LPC11xx/platform.mk +++ b/os/hal/platforms/LPC11xx/platform.mk @@ -1,8 +1,12 @@  # List of all the LPC11xx platform files.
  PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/LPC11xx/hal_lld.c \
 -              ${CHIBIOS}/os/hal/platforms/LPC11xx/gpt_lld.c \
                ${CHIBIOS}/os/hal/platforms/LPC11xx/pal_lld.c \
 +              ${CHIBIOS}/os/hal/platforms/LPC11xx/ext_lld.c \
 +              ${CHIBIOS}/os/hal/platforms/LPC11xx/ext_lld_isr.c \
 +              ${CHIBIOS}/os/hal/platforms/LPC11xx/gpt_lld.c \
 +              ${CHIBIOS}/os/hal/platforms/LPC11xx/pwm_lld.c \
                ${CHIBIOS}/os/hal/platforms/LPC11xx/serial_lld.c \
 +              ${CHIBIOS}/os/hal/platforms/LPC11xx/i2c_lld.c \
                ${CHIBIOS}/os/hal/platforms/LPC11xx/spi_lld.c
  # Required include directories
 diff --git a/os/hal/platforms/LPC11xx/pwm_lld.c b/os/hal/platforms/LPC11xx/pwm_lld.c new file mode 100644 index 000000000..06de0bbc6 --- /dev/null +++ b/os/hal/platforms/LPC11xx/pwm_lld.c @@ -0,0 +1,407 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
 +    LPC11xx PWM driver - Copyright (C) 2013 Marcin Jokel
 +
 +    Licensed under the Apache License, Version 2.0 (the "License");
 +    you may not use this file except in compliance with the License.
 +    You may obtain a copy of the License at
 +
 +        http://www.apache.org/licenses/LICENSE-2.0
 +
 +    Unless required by applicable law or agreed to in writing, software
 +    distributed under the License is distributed on an "AS IS" BASIS,
 +    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 +    See the License for the specific language governing permissions and
 +    limitations under the License.
 +*/
 +
 +/**
 + * @file    LPC11xx/pwm_lld.c
 + * @brief   LPC11xx PWM subsystem low level driver header.
 + *
 + * @addtogroup PWM
 + * @{
 + */
 +
 +#include "ch.h"
 +#include "hal.h"
 +
 +#if HAL_USE_PWM || defined(__DOXYGEN__)
 +
 +/*===========================================================================*/
 +/* Driver local definitions.                                                 */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver exported variables.                                                */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   PWMD1 driver identifier.
 + * @note    The driver PWMD1 allocates the complex timer TIM1 when enabled.
 + */
 +#if LPC11xx_PWM_USE_CT16B0 || defined(__DOXYGEN__)
 +PWMDriver PWMD1;
 +#endif
 +
 +/**
 + * @brief   PWMD2 driver identifier.
 + * @note    The driver PWMD2 allocates the timer TIM2 when enabled.
 + */
 +#if LPC11xx_PWM_USE_CT16B1 || defined(__DOXYGEN__)
 +PWMDriver PWMD2;
 +#endif
 +
 +/**
 + * @brief   PWMD3 driver identifier.
 + * @note    The driver PWMD3 allocates the timer TIM3 when enabled.
 + */
 +#if LPC11xx_PWM_USE_CT32B0 || defined(__DOXYGEN__)
 +PWMDriver PWMD3;
 +#endif
 +
 +/**
 + * @brief   PWMD4 driver identifier.
 + * @note    The driver PWMD4 allocates the timer TIM4 when enabled.
 + */
 +#if LPC11xx_PWM_USE_CT32B1 || defined(__DOXYGEN__)
 +PWMDriver PWMD4;
 +#endif
 +
 +/*===========================================================================*/
 +/* Driver local variables and types.                                         */
 +/*===========================================================================*/
 +
 +/*===========================================================================*/
 +/* Driver local functions.                                                   */
 +/*===========================================================================*/
 +
 +#if LPC11xx_PWM_USE_CT16B0 || LPC11xx_PWM_USE_CT16B1 || LPC11xx_PWM_USE_CT32B0 ||       \
 +    LPC11xx_PWM_USE_CT32B1 || defined(__DOXYGEN__)
 +/**
 + * @brief   Common TIM2...TIM5 IRQ handler.
 + * @note    It is assumed that the various sources are only activated if the
 + *          associated callback pointer is not equal to @p NULL in order to not
 + *          perform an extra check in a potentially critical interrupt handler.
 + *
 + * @param[in] pwmp      pointer to a @p PWMDriver object
 + */
 +static void pwm_lld_serve_interrupt(PWMDriver *pwmp) {
 +  uint16_t sr;
 +
 +  sr  = pwmp->tim->IR;
 +  pwmp->tim->IR = sr;
 +  if ((sr & IR_MR0INT) != 0)
 +    pwmp->config->channels[0].callback(pwmp);
 +  if ((sr & IR_MR1INT) != 0)
 +    pwmp->config->channels[1].callback(pwmp);
 +  if ((sr & IR_MR3INT) != 0)
 +    pwmp->config->callback(pwmp);
 +}
 +#endif /* STM32_PWM_USE_TIM2 || ... || STM32_PWM_USE_TIM5 */
 +
 +/*===========================================================================*/
 +/* Driver interrupt handlers.                                                */
 +/*===========================================================================*/
 +
 +#if LPC11xx_PWM_USE_CT16B0 || defined(__DOXYGEN__)
 +/**
 + * @brief   CT16B0 interrupt handler.
 + *
 + * @isr
 + */
 +CH_IRQ_HANDLER(Vector80) {
 +
 +  CH_IRQ_PROLOGUE();
 +
 +  pwm_lld_serve_interrupt(&PWMD1);
 +
 +  CH_IRQ_EPILOGUE();
 +}
 +
 +#endif /* STM32_PWM_USE_TIM1 */
 +
 +#if LPC11xx_PWM_USE_CT16B1 || defined(__DOXYGEN__)
 +/**
 + * @brief   CT16B1 interrupt handler.
 + *
 + * @isr
 + */
 +CH_IRQ_HANDLER(Vector84) {
 +
 +  CH_IRQ_PROLOGUE();
 +
 +  pwm_lld_serve_interrupt(&PWMD2);
 +
 +  CH_IRQ_EPILOGUE();
 +}
 +#endif /* LPC11xx_PWM_USE_CT16B1 */
 +
 +#if LPC11xx_PWM_USE_CT32B0 || defined(__DOXYGEN__)
 +/**
 + * @brief   CT32B0 interrupt handler.
 + *
 + * @isr
 + */
 +CH_IRQ_HANDLER(Vector88) {
 +
 +  CH_IRQ_PROLOGUE();
 +
 +  pwm_lld_serve_interrupt(&PWMD3);
 +
 +  CH_IRQ_EPILOGUE();
 +}
 +#endif /* LPC11xx_PWM_USE_CT32B0 */
 +
 +#if LPC11xx_PWM_USE_CT32B1 || defined(__DOXYGEN__)
 +/**
 + * @brief   CT32B1 interrupt handler.
 + *
 + * @isr
 + */
 +CH_IRQ_HANDLER(Vector8C) {
 +
 +  CH_IRQ_PROLOGUE();
 +
 +  pwm_lld_serve_interrupt(&PWMD4);
 +
 +  CH_IRQ_EPILOGUE();
 +}
 +#endif /* LPC11xx_PWM_USE_CT32B1 */
 +
 +/*===========================================================================*/
 +/* Driver exported functions.                                                */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   Low level PWM driver initialization.
 + *
 + * @notapi
 + */
 +void pwm_lld_init(void) {
 +
 +#if LPC11xx_PWM_USE_CT16B0
 +  /* Driver initialization.*/
 +  pwmObjectInit(&PWMD1);
 +  PWMD1.tim = LPC_TMR16B0;
 +
 +#if LPC11xx_PWM_USE_CT16B0_CH0
 +  LPC_IOCON->PIO0_8 = 0xC2;
 +#endif
 +
 +#if LPC11xx_PWM_USE_CT16B0_CH1
 +  LPC_IOCON->PIO0_9 = 0xC2;
 +#endif
 +#endif
 +
 +#if LPC11xx_PWM_USE_CT16B1
 +  /* Driver initialization.*/
 +  pwmObjectInit(&PWMD2);
 +  PWMD2.tim = LPC_TMR16B1;
 +
 +#if LPC11xx_PWM_USE_CT16B1_CH0
 +  LPC_IOCON->PIO1_9 = 0xC1;
 +#endif
 +
 +#if LPC11xx_PWM_USE_CT16B1_CH1
 +  LPC_IOCON->PIO1_10 = 0xC2;
 +#endif
 +#endif
 +
 +#if LPC11xx_PWM_USE_CT32B0
 +  /* Driver initialization.*/
 +  pwmObjectInit(&PWMD3);
 +  PWMD3.tim = LPC_TMR32B0;
 +
 +#if LPC11xx_PWM_USE_CT32B0_CH0
 +  LPC_IOCON->PIO1_6 = 0xC2;
 +#endif
 +
 +#if  LPC11xx_PWM_USE_CT32B0_CH1
 +  LPC_IOCON->PIO1_7 = 0xC2;
 +#endif
 +#endif
 +
 +#if LPC11xx_PWM_USE_CT32B1
 +  /* Driver initialization.*/
 +  pwmObjectInit(&PWMD4);
 +  PWMD4.tim = LPC_TMR32B1;
 +
 +#if LPC11xx_PWM_USE_CT32B1_CH0
 +  LPC_IOCON->R_PIO1_1 = 0xC3;
 +#endif
 +
 +#if LPC11xx_PWM_USE_CT32B1_CH1
 +  LPC_IOCON->R_PIO1_2 = 0xC3;
 +#endif
 +#endif
 +}
 +
 +/**
 + * @brief   Configures and activates the PWM peripheral.
 + * @note    Starting a driver that is already in the @p PWM_READY state
 + *          disables all the active channels.
 + *
 + * @param[in] pwmp      pointer to a @p PWMDriver object
 + *
 + * @notapi
 + */
 +void pwm_lld_start(PWMDriver *pwmp) {
 +  uint32_t pr;
 +
 +  if (pwmp->state == PWM_STOP) {
 +    /* Clock activation and timer reset.*/
 +#if LPC11xx_PWM_USE_CT16B0
 +    if (&PWMD1 == pwmp) {
 +      LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7);
 +      nvicEnableVector(TIMER_16_0_IRQn, LPC11xx_PWM_CT16B0_IRQ_PRIORITY);
 +    }
 +#endif
 +#if LPC11xx_PWM_USE_CT16B1
 +    if (&PWMD2 == pwmp) {
 +      LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8);
 +      nvicEnableVector(TIMER_16_1_IRQn, LPC11xx_PWM_CT16B1_IRQ_PRIORITY);
 +    }
 +#endif
 +#if LPC11xx_PWM_USE_CT32B0
 +    if (&PWMD3 == pwmp) {
 +      LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9);
 +      nvicEnableVector(TIMER_32_0_IRQn, LPC11xx_PWM_CT32B0_IRQ_PRIORITY);
 +    }
 +#endif
 +#if LPC11xx_PWM_USE_CT32B1
 +     if (&PWMD4 == pwmp) {
 +       LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 10);
 +       nvicEnableVector(TIMER_32_1_IRQn, LPC11xx_PWM_CT32B1_IRQ_PRIORITY);
 +     }
 +#endif
 +  }
 +  else {
 +    /* Driver re-configuration scenario, it must be stopped first.*/
 +    pwmp->tim->TCR = 0;
 +  }
 +
 +  /* Output enables and polarities setup.*/
 +    if(pwmp->config->channels[0].mode == PWM_OUTPUT_ACTIVE_LOW)
 +        pwmp->tim->PWMC = (1 << 0);
 +
 +    if(pwmp->config->channels[1].mode == PWM_OUTPUT_ACTIVE_LOW)
 +          pwmp->tim->PWMC |= (1 << 1);
 +
 +    /* Timer configured and started.*/
 +    pr = (uint16_t)((LPC11xx_SYSCLK / pwmp->config->frequency) - 1);
 +    chDbgAssert(((uint32_t)(pr + 1) * pwmp->config->frequency) == LPC11xx_SYSCLK,
 +                    "pwm_lld_start(), #1", "invalid frequency");
 +
 +    pwmp->tim->TC = 0;
 +    pwmp->tim->PR  = pr;
 +    pwmp->tim->IR  = 0xFF;
 +    pwmp->tim->MCR = MCR_MR3R;              /* Reset on Match3 */
 +    pwmp->tim->MR3 = pwmp->config->period;
 +
 +    if (pwmp->config->callback != NULL)
 +        pwmp->tim->MCR |= MCR_MR3I;
 +
 +    pwmp->tim->TCR = 1;                     /* Timer start */
 +}
 +
 +/**
 + * @brief   Deactivates the PWM peripheral.
 + *
 + * @param[in] pwmp      pointer to a @p PWMDriver object
 + *
 + * @notapi
 + */
 +void pwm_lld_stop(PWMDriver *pwmp) {
 +
 +  /* If in ready state then disables the PWM clock.*/
 +  if (pwmp->state == PWM_READY) {
 +    pwmp->tim->TCR = 0;                     /* Timer disabled.              */
 +    pwmp->tim->MCR = 0;                     /* All IRQs disabled.           */
 +    pwmp->tim->IR  = 0xFF;                  /* Clear eventual pending IRQs. */
 +    pwmp->tim->PWMC = 0;                    /* PWM outputs disable.         */
 +
 +#if LPC11xx_PWM_USE_CT16B0
 +    if (&PWMD1 == pwmp) {
 +      nvicDisableVector(TIMER_16_0_IRQn);
 +      LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 7);
 +    }
 +#endif
 +#if LPC11xx_PWM_USE_CT16B1
 +    if (&PWMD2 == pwmp) {
 +      nvicDisableVector(TIMER_16_1_IRQn);
 +      LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 8);
 +    }
 +#endif
 +#if LPC11xx_PWM_USE_CT32B0
 +    if (&PWMD3 == pwmp) {
 +      nvicDisableVector(TIMER_32_0_IRQn);
 +      LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 9);
 +    }
 +#endif
 +#if LPC11xx_PWM_USE_CT32B1
 +    if (&PWMD4 == pwmp) {
 +      nvicDisableVector(TIMER_32_1_IRQn);
 +      LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 10);
 +    }
 +#endif
 +
 +  }
 +}
 +
 +/**
 + * @brief   Enables a PWM channel.
 + * @pre     The PWM unit must have been activated using @p pwmStart().
 + * @post    The channel is active using the specified configuration.
 + * @note    The function has effect at the next cycle start.
 + *
 + * @param[in] pwmp      pointer to a @p PWMDriver object
 + * @param[in] channel   PWM channel identifier (0...PWM_CHANNELS-1)
 + * @param[in] width     PWM pulse width as clock pulses number
 + *
 + * @notapi
 + */
 +void pwm_lld_enable_channel(PWMDriver *pwmp,
 +                            pwmchannel_t channel,
 +                            pwmcnt_t width) {
 +
 +  pwmp->tim->MCR &= ~(7 << (channel * 3));
 +
 +  if ( channel == 0)
 +    pwmp->tim->MR0 = width;                  /* New duty cycle.      */
 +  else
 +    pwmp->tim->MR1 = width;                  /* New duty cycle.      */
 +  /* If there is a callback defined for the channel then the associated
 +     interrupt must be enabled.*/
 +  if (pwmp->config->channels[channel].callback != NULL) {
 +    pwmp->tim->IR = (1 << channel);         /* Clear interrupt flag*/
 +    pwmp->tim->MCR |= (1 << (channel * 3)); /* Set interrupt on selected channel */
 +  }
 +
 +}
 +
 +/**
 + * @brief   Disables a PWM channel.
 + * @pre     The PWM unit must have been activated using @p pwmStart().
 + * @post    The channel is disabled and its output line returned to the
 + *          idle state.
 + * @note    The function has effect at the next cycle start.
 + *
 + * @param[in] pwmp      pointer to a @p PWMDriver object
 + * @param[in] channel   PWM channel identifier (0...PWM_CHANNELS-1)
 + *
 + * @notapi
 + */
 +void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
 +
 +  if ( channel == 0)
 +    pwmp->tim->MR0 = 0;
 +  else
 +    pwmp->tim->MR1 = 0;
 +  pwmp->tim->MCR &= ~(7 << (channel * 3));
 +  pwmp->tim->IR = (1 << channel);
 +}
 +
 +#endif /* HAL_USE_PWM */
 +
 +/** @} */
 diff --git a/os/hal/platforms/LPC11xx/pwm_lld.h b/os/hal/platforms/LPC11xx/pwm_lld.h new file mode 100644 index 000000000..2b3a37fd1 --- /dev/null +++ b/os/hal/platforms/LPC11xx/pwm_lld.h @@ -0,0 +1,364 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
 +    LPC11xx PWM driver - Copyright (C) 2013 Marcin Jokel
 +
 +    Licensed under the Apache License, Version 2.0 (the "License");
 +    you may not use this file except in compliance with the License.
 +    You may obtain a copy of the License at
 +
 +        http://www.apache.org/licenses/LICENSE-2.0
 +
 +    Unless required by applicable law or agreed to in writing, software
 +    distributed under the License is distributed on an "AS IS" BASIS,
 +    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 +    See the License for the specific language governing permissions and
 +    limitations under the License.
 +*/
 +
 +/**
 + * @file    LPC11xx/pwm_lld.h
 + * @brief   LPC11xx PWM subsystem low level driver header.
 + *
 + * @addtogroup PWM
 + * @{
 + */
 +
 +#ifndef _PWM_LLD_H_
 +#define _PWM_LLD_H_
 +
 +#if HAL_USE_PWM || defined(__DOXYGEN__)
 +
 +/*===========================================================================*/
 +/* Unsupported modes and specific modes                                      */
 +/*===========================================================================*/
 +#undef PWM_OUTPUT_ACTIVE_HIGH
 +
 +/*===========================================================================*/
 +/* Driver constants.                                                         */
 +/*===========================================================================*/
 +
 +#define IR_MR0INT   (1 << 0)
 +#define IR_MR1INT   (1 << 1)
 +#define IR_MR2INT   (1 << 2)
 +#define IR_MR3INT   (1 << 3)
 +#define IR_CR0INT   (1 << 4)
 +#define IR_CR1INT   (1 << 5)
 +#define IR_CR2INT   (1 << 6)
 +#define IR_CR3INT   (1 << 7)
 +
 +#define MCR_MR3I    (1 << 9)
 +#define MCR_MR3R    (1 << 10)
 +#define MCR_MR3S    (1 << 11)
 +/**
 + * @brief   Number of PWM channels per PWM driver.
 + */
 +#define PWM_CHANNELS                            2
 +
 +/*===========================================================================*/
 +/* Driver pre-compile time settings.                                         */
 +/*===========================================================================*/
 +
 +/**
 + * @name    Configuration options
 + * @{
 + */
 +
 +/**
 + * @brief   PWMD1 driver enable switch.
 + * @details If set to @p TRUE the support for PWMD1 is included.
 + * @note    The default is @p TRUE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT16B0) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT16B0                  FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD2 driver enable switch.
 + * @details If set to @p TRUE the support for PWMD2 is included.
 + * @note    The default is @p TRUE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT16B1) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT16B1                  FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD3 driver enable switch.
 + * @details If set to @p TRUE the support for PWMD3 is included.
 + * @note    The default is @p TRUE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT32B0) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT32B0                  FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD4 driver enable switch.
 + * @details If set to @p TRUE the support for PWMD4 is included.
 + * @note    The default is @p TRUE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT32B1) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT32B1                  FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD1 Channel 0 driver enable switch.
 + * @details If set to @p TRUE PWMD1 Channel 0 is enabled.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT16B0_CH0) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT16B0_CH0             FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD1 Channel 1 driver enable switch.
 + * @details If set to @p TRUE PWMD1 Channel 1 is enabled.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT16B0_CH1) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT16B0_CH1             FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD2 Channel 0 driver enable switch.
 + * @details If set to @p TRUE PWMD2 Channel 0 is enabled.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT16B1_CH0) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT16B1_CH0             FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD2 Channel 1 driver enable switch.
 + * @details If set to @p TRUE PWMD2 Channel 1 is enabled.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT16B1_CH1) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT16B1_CH1             FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD3 Channel 0 driver enable switch.
 + * @details If set to @p TRUE PWMD3 Channel 0 is enabled.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT32B0_CH0) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT32B0_CH0             FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD3 Channel 1 driver enable switch.
 + * @details If set to @p TRUE PWMD3 Channel 1 is enabled.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT32B0_CH1) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT32B0_CH1             FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD4 Channel 0 driver enable switch.
 + * @details If set to @p TRUE PWMD4 Channel 0 is enabled.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT32B1_CH0) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT32B1_CH0             FALSE
 +#endif
 +
 +/**
 + * @brief   PWMD4 Channel 1 driver enable switch.
 + * @details If set to @p TRUE PWMD4 Channel 1 is enabled.
 + * @note    The default is @p FALSE.
 + */
 +#if !defined(LPC11xx_PWM_USE_CT32B1_CH1) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_USE_CT32B1_CH1             FALSE
 +#endif
 +/**
 + * @brief   PWMD1 interrupt priority level setting.
 + */
 +#if !defined(LPC11xx_PWM_CT16B0_IRQ_PRIORITY) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_CT16B0_IRQ_PRIORITY         3
 +#endif
 +
 +/**
 + * @brief   PWMD2 interrupt priority level setting.
 + */
 +#if !defined(LPC11xx_PWM_CT16B1_IRQ_PRIORITY) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_CT16B1_IRQ_PRIORITY         3
 +#endif
 +
 +/**
 + * @brief   PWMD3 interrupt priority level setting.
 + */
 +#if !defined(LPC11xx_PWM_CT32B0_IRQ_PRIORITY) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_CT32B0_IRQ_PRIORITY         3
 +#endif
 +
 +/**
 + * @brief   PWMD4 interrupt priority level setting.
 + */
 +#if !defined(LPC11xx_PWM_CT32B1_IRQ_PRIORITY) || defined(__DOXYGEN__)
 +#define LPC11xx_PWM_CT32B1_IRQ_PRIORITY         3
 +#endif
 +
 +/*===========================================================================*/
 +/* Configuration checks.                                                     */
 +/*===========================================================================*/
 +
 +
 +
 +/*===========================================================================*/
 +/* Driver data structures and types.                                         */
 +/*===========================================================================*/
 +
 +/**
 + * @brief PWM mode type.
 + */
 +typedef uint32_t pwmmode_t;
 +
 +/**
 + * @brief   PWM channel type.
 + */
 +typedef uint8_t pwmchannel_t;
 +
 +/**
 + * @brief   PWM counter type.
 + */
 +typedef uint16_t pwmcnt_t;
 +
 +/**
 + * @brief   PWM driver channel configuration structure.
 + */
 +typedef struct {
 +  /**
 +   * @brief Channel active logic level.
 +   */
 +  pwmmode_t                 mode;
 +  /**
 +   * @brief Channel callback pointer.
 +   * @note  This callback is invoked on the channel compare event. If set to
 +   *        @p NULL then the callback is disabled.
 +   */
 +  pwmcallback_t             callback;
 +  /* End of the mandatory fields.*/
 +} PWMChannelConfig;
 +
 +/**
 + * @brief   PWM driver configuration structure.
 + */
 +typedef struct {
 +  /**
 +   * @brief   Timer clock in Hz.
 +   * @note    The low level can use assertions in order to catch invalid
 +   *          frequency specifications.
 +   */
 +  uint32_t                  frequency;
 +  /**
 +   * @brief   PWM period in ticks.
 +   * @note    The low level can use assertions in order to catch invalid
 +   *          period specifications.
 +   */
 +  pwmcnt_t                  period;
 +  /**
 +   * @brief Periodic callback pointer.
 +   * @note  This callback is invoked on PWM counter reset. If set to
 +   *        @p NULL then the callback is disabled.
 +   */
 +  pwmcallback_t             callback;
 +  /**
 +   * @brief Channels configurations.
 +   */
 +  PWMChannelConfig          channels[PWM_CHANNELS];
 +  /* End of the mandatory fields.*/
 +
 +} PWMConfig;
 +
 +/**
 + * @brief   Structure representing a PWM driver.
 + */
 +struct PWMDriver {
 +  /**
 +   * @brief Driver state.
 +   */
 +  pwmstate_t                state;
 +  /**
 +   * @brief Current driver configuration data.
 +   */
 +  const PWMConfig           *config;
 +  /**
 +   * @brief   Current PWM period in ticks.
 +   */
 +  pwmcnt_t                  period;
 +#if defined(PWM_DRIVER_EXT_FIELDS)
 +  PWM_DRIVER_EXT_FIELDS
 +#endif
 +  /* End of the mandatory fields.*/
 +  /**
 +   * @brief Timer base clock.
 +   */
 +  uint32_t                  clock;
 +  /**
 +   * @brief Pointer to the TIMx registers block.
 +   */
 +  LPC_TMR_TypeDef           *tim;
 +};
 +
 +/*===========================================================================*/
 +/* Driver macros.                                                            */
 +/*===========================================================================*/
 +
 +/**
 + * @brief   Changes the period the PWM peripheral.
 + * @details This function changes the period of a PWM unit that has already
 + *          been activated using @p pwmStart().
 + * @pre     The PWM unit must have been activated using @p pwmStart().
 + * @post    The PWM unit period is changed to the new value.
 + * @note    The function has effect at the next cycle start.
 + * @note    If a period is specified that is shorter than the pulse width
 + *          programmed in one of the channels then the behavior is not
 + *          guaranteed.
 + *
 + * @param[in] pwmp      pointer to a @p PWMDriver object
 + * @param[in] period    new cycle time in ticks
 + *
 + * @notapi
 + */
 +#define pwm_lld_change_period(pwmp, period)                                 \
 +  ((pwmp)->tim->MR3 = (period))
 +
 +/*===========================================================================*/
 +/* External declarations.                                                    */
 +/*===========================================================================*/
 +
 +#if LPC11xx_PWM_USE_CT16B0 && !defined(__DOXYGEN__)
 +extern PWMDriver PWMD1;
 +#endif
 +
 +#if LPC11xx_PWM_USE_CT16B1 && !defined(__DOXYGEN__)
 +extern PWMDriver PWMD2;
 +#endif
 +
 +#if LPC11xx_PWM_USE_CT32B0 && !defined(__DOXYGEN__)
 +extern PWMDriver PWMD3;
 +#endif
 +
 +#if LPC11xx_PWM_USE_CT32B1 && !defined(__DOXYGEN__)
 +extern PWMDriver PWMD4;
 +#endif
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +  void pwm_lld_init(void);
 +  void pwm_lld_start(PWMDriver *pwmp);
 +  void pwm_lld_stop(PWMDriver *pwmp);
 +  void pwm_lld_enable_channel(PWMDriver *pwmp,
 +                              pwmchannel_t channel,
 +                              pwmcnt_t width);
 +  void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel);
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#endif /* HAL_USE_PWM */
 +
 +#endif /* _PWM_LLD_H_ */
 +
 +/** @} */
 diff --git a/os/ports/GCC/ARMCMx/LPC11xx/ld/LPC11C24.ld b/os/ports/GCC/ARMCMx/LPC11xx/ld/LPC11C24.ld new file mode 100644 index 000000000..1022db9ab --- /dev/null +++ b/os/ports/GCC/ARMCMx/LPC11xx/ld/LPC11C24.ld @@ -0,0 +1,152 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
 +                 2011,2012,2013 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/*
 + * LPC11C24 memory setup.
 + */
 +__main_stack_size__     = 0x0200;
 +__process_stack_size__  = 0x0200;
 +
 +MEMORY
 +{
 +    flash : org = 0x00000000, len = 32k
 +    ram : org = 0x10000000, len = 8k
 +}
 +
 +__ram_start__           = ORIGIN(ram);
 +__ram_size__            = LENGTH(ram);
 +__ram_end__             = __ram_start__ + __ram_size__;
 +
 +ENTRY(ResetHandler)
 +
 +SECTIONS
 +{
 +    . = 0;
 +    _text = .;
 +
 +    startup : ALIGN(16) SUBALIGN(16)
 +    {
 +        KEEP(*(vectors))
 +    } > flash
 +
 +    constructors : ALIGN(4) SUBALIGN(4)
 +    {
 +        PROVIDE(__init_array_start = .);
 +        KEEP(*(SORT(.init_array.*)))
 +        KEEP(*(.init_array))
 +        PROVIDE(__init_array_end = .);
 +    } > flash
 +
 +    destructors : ALIGN(4) SUBALIGN(4)
 +    {
 +        PROVIDE(__fini_array_start = .);
 +        KEEP(*(.fini_array))
 +        KEEP(*(SORT(.fini_array.*)))
 +        PROVIDE(__fini_array_end = .);
 +    } > flash
 +
 +    .text : ALIGN(16) SUBALIGN(16)
 +    {
 +        *(.text.startup.*)
 +        *(.text)
 +        *(.text.*)
 +        *(.rodata)
 +        *(.rodata.*)
 +        *(.glue_7t)
 +        *(.glue_7)
 +        *(.gcc*)
 +    } > flash
 +
 +    .ARM.extab :
 +    {
 +        *(.ARM.extab* .gnu.linkonce.armextab.*)
 +    } > flash
 +
 +    .ARM.exidx : {
 +        PROVIDE(__exidx_start = .);
 +        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
 +        PROVIDE(__exidx_end = .);
 +     } > flash
 +
 +    .eh_frame_hdr :
 +    {
 +        *(.eh_frame_hdr)
 +    } > flash
 +
 +    .eh_frame : ONLY_IF_RO
 +    {
 +        *(.eh_frame)
 +    } > flash
 +    
 +    .textalign : ONLY_IF_RO
 +    {
 +        . = ALIGN(8);
 +    } > flash
 +
 +    _etext = .;
 +    _textdata = _etext;
 +
 +    .stacks :
 +    {
 +        . = ALIGN(8);
 +        __main_stack_base__ = .;
 +        . += __main_stack_size__;
 +        . = ALIGN(8);
 +        __main_stack_end__ = .;
 +        __process_stack_base__ = .;
 +        __main_thread_stack_base__ = .;
 +        . += __process_stack_size__;
 +        . = ALIGN(8);
 +        __process_stack_end__ = .;
 +        __main_thread_stack_end__ = .;
 +    } > ram
 +
 +    .data :
 +    {
 +        . = ALIGN(4);
 +        PROVIDE(_data = .);
 +        *(.data)
 +        . = ALIGN(4);
 +        *(.data.*)
 +        . = ALIGN(4);
 +        *(.ramtext)
 +        . = ALIGN(4);
 +        PROVIDE(_edata = .);
 +    } > ram AT > flash
 +
 +    .bss :
 +    {
 +        . = ALIGN(4);
 +        PROVIDE(_bss_start = .);
 +        *(.bss)
 +        . = ALIGN(4);
 +        *(.bss.*)
 +        . = ALIGN(4);
 +        *(COMMON)
 +        . = ALIGN(4);
 +        PROVIDE(_bss_end = .);
 +    } > ram    
 +}
 +
 +PROVIDE(end = .);
 +_end            = .;
 +
 +__heap_base__   = _end;
 +__heap_end__    = __ram_end__;
  | 
