diff options
Diffstat (limited to 'os')
| -rw-r--r-- | os/hal/ports/KINETIS/LLD/hal_serial_lld.c | 251 | ||||
| -rw-r--r-- | os/hal/ports/KINETIS/LLD/hal_serial_lld.h | 69 | 
2 files changed, 248 insertions, 72 deletions
| diff --git a/os/hal/ports/KINETIS/LLD/hal_serial_lld.c b/os/hal/ports/KINETIS/LLD/hal_serial_lld.c index c80cf22..c92fa5c 100644 --- a/os/hal/ports/KINETIS/LLD/hal_serial_lld.c +++ b/os/hal/ports/KINETIS/LLD/hal_serial_lld.c @@ -1,5 +1,6 @@  /*
      ChibiOS - Copyright (C) 2013-2015 Fabio Utzig
 +              Copyright (C) 2017 Wim Lewis
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
 @@ -50,6 +51,18 @@ SerialDriver SD2;  SerialDriver SD3;
  #endif
 +#if KINETIS_SERIAL_USE_UART3 || defined(__DOXYGEN__)
 +SerialDriver SD4;
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART4 || defined(__DOXYGEN__)
 +SerialDriver SD5;
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART5 || defined(__DOXYGEN__)
 +SerialDriver SD6;
 +#endif
 +
  /*===========================================================================*/
  /* Driver local variables and types.                                         */
  /*===========================================================================*/
 @@ -95,33 +108,37 @@ static void serve_error_interrupt(SerialDriver *sdp) {    UART_w_TypeDef *u = &(sdp->uart);
    uint8_t s1 = *(u->s1_p);
 -  /* S1 bits are write-1-to-clear for UART0 on KL2x. */
 -  /* Clearing on K20x and KL2x/UART>0 is done by reading S1 and
 +  /* Clearing on K20x, K60x, and KL2x/UART>0 is done by reading S1 and
     * then reading D.*/
 -#if defined(KL2x) && KINETIS_SERIAL_USE_UART0
 -  if(sdp == &SD1) {
 -    if(s1 & UARTx_S1_IDLE) {
 -      *(u->s1_p) |= UARTx_S1_IDLE;
 -    }
 +  if(s1 & UARTx_S1_IDLE) {
 +    (void)*(u->d_p);
 +  }
 -    if(s1 & (UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF)) {
 -      set_error(sdp, s1);
 -      *(u->s1_p) |= UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF;
 -    }
 -    return;
 +  if(s1 & (UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF)) {
 +    set_error(sdp, s1);
 +    (void)*(u->d_p);
    }
 -#endif /* KL2x && KINETIS_SERIAL_USE_UART0 */
 +}
 +
 +#if defined(KL2x) && KINETIS_SERIAL_USE_UART0
 +static void serve_error_interrupt_uart0(void) {
 +  SerialDriver *sdp = &SD1;
 +  UART_w_TypeDef *u = &(sdp->uart);
 +  uint8_t s1 = *(u->s1_p);
 +
 +  /* S1 bits are write-1-to-clear for UART0 on KL2x. */
    if(s1 & UARTx_S1_IDLE) {
 -    (void)*(u->d_p);
 +    *(u->s1_p) |= UARTx_S1_IDLE;
    }
    if(s1 & (UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF)) {
      set_error(sdp, s1);
 -    (void)*(u->d_p);
 +    *(u->s1_p) |= UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF;
    }
  }
 +#endif /* KL2x && KINETIS_SERIAL_USE_UART0 */
  /**
   * @brief   Common IRQ handler.
 @@ -161,6 +178,12 @@ static void serve_interrupt(SerialDriver *sdp) {      }
    }
 +#if defined(KL2x) && KINETIS_SERIAL_USE_UART0
 +  if (sdp == &SD1) {
 +    serve_error_interrupt_uart0();
 +    return;
 +  }
 +#endif
    serve_error_interrupt(sdp);
  }
 @@ -184,29 +207,28 @@ static void preload(SerialDriver *sdp) {  /**
   * @brief   Driver output notification.
   */
 -#if KINETIS_SERIAL_USE_UART0 || defined(__DOXYGEN__)
 -static void notify1(io_queue_t *qp)
 +static void notify(io_queue_t *qp)
  {
 -  (void)qp;
 -  preload(&SD1);
 +  preload(qp->q_link);
  }
 -#endif
 -#if KINETIS_SERIAL_USE_UART1 || defined(__DOXYGEN__)
 -static void notify2(io_queue_t *qp)
 -{
 -  (void)qp;
 -  preload(&SD2);
 -}
 -#endif
 -
 -#if KINETIS_SERIAL_USE_UART2 || defined(__DOXYGEN__)
 -static void notify3(io_queue_t *qp)
 -{
 -  (void)qp;
 -  preload(&SD3);
 +/**
 + * @brief   Common driver initialization, except LP.
 + */
 +static void sd_lld_init_driver(SerialDriver *SDn, UART_TypeDef *UARTn) {
 +  /* Driver initialization.*/
 +  sdObjectInit(SDn, NULL, notify);
 +  SDn->uart.bdh_p = &(UARTn->BDH);
 +  SDn->uart.bdl_p = &(UARTn->BDL);
 +  SDn->uart.c1_p =  &(UARTn->C1);
 +  SDn->uart.c2_p =  &(UARTn->C2);
 +  SDn->uart.c3_p =  &(UARTn->C3);
 +  SDn->uart.c4_p =  &(UARTn->C4);
 +  SDn->uart.s1_p =  (volatile uint8_t *)&(UARTn->S1);
 +  SDn->uart.s2_p =  &(UARTn->S2);
 +  SDn->uart.d_p =   &(UARTn->D);
 +  SDn->uart.uart_p = UARTn;
  }
 -#endif
  /**
   * @brief   Common UART configuration.
 @@ -240,9 +262,9 @@ static void configure_uart(SerialDriver *sdp, const SerialConfig *config) {    }
  #endif /* KINETIS_SERIAL_USE_UART0 */
 -#elif defined(K20x) /* KL2x */
 +#elif defined(K20x) || defined(K60x) /* KL2x */
 -  /* UARTs 0 and 1 are clocked from SYSCLK, others from BUSCLK on K20x. */
 +  /* UARTs 0 and 1 are clocked from SYSCLK, others from BUSCLK on K20x and K60x. */
  #if KINETIS_SERIAL_USE_UART0
    if(sdp == &SD1)
      divisor = KINETIS_SYSCLK_FREQUENCY;
 @@ -260,9 +282,9 @@ static void configure_uart(SerialDriver *sdp, const SerialConfig *config) {    *(uart->bdh_p) = UARTx_BDH_SBR(divisor >> 13) | (*(uart->bdh_p) & ~UARTx_BDH_SBR_MASK);
    *(uart->bdl_p) = UARTx_BDL_SBR(divisor >> 5);
 -#if defined(K20x)
 +#if defined(K20x) || defined(K60x)
    *(uart->c4_p) = UARTx_C4_BRFA(divisor) | (*(uart->c4_p) & ~UARTx_C4_BRFA_MASK);
 -#endif /* K20x */
 +#endif /* K20x, K60x */
    /* Line settings. */
    *(uart->c1_p) = 0;
 @@ -300,12 +322,40 @@ OSAL_IRQ_HANDLER(KINETIS_SERIAL2_IRQ_VECTOR) {  }
  #endif
 +#if KINETIS_SERIAL_USE_UART3 || defined(__DOXYGEN__)
 +OSAL_IRQ_HANDLER(KINETIS_SERIAL3_IRQ_VECTOR) {
 +  OSAL_IRQ_PROLOGUE();
 +  serve_interrupt(&SD4);
 +  OSAL_IRQ_EPILOGUE();
 +}
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART4 || defined(__DOXYGEN__)
 +OSAL_IRQ_HANDLER(KINETIS_SERIAL4_IRQ_VECTOR) {
 +  OSAL_IRQ_PROLOGUE();
 +  serve_interrupt(&SD5);
 +  OSAL_IRQ_EPILOGUE();
 +}
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART5 || defined(__DOXYGEN__)
 +OSAL_IRQ_HANDLER(KINETIS_SERIAL5_IRQ_VECTOR) {
 +  OSAL_IRQ_PROLOGUE();
 +  serve_interrupt(&SD6);
 +  OSAL_IRQ_EPILOGUE();
 +}
 +#endif
 +
  #if KINETIS_HAS_SERIAL_ERROR_IRQ
  #if KINETIS_SERIAL_USE_UART0 || defined(__DOXYGEN__)
  OSAL_IRQ_HANDLER(KINETIS_SERIAL0_ERROR_IRQ_VECTOR) {
    OSAL_IRQ_PROLOGUE();
 +#if defined(KL2x)
 +  serve_error_interrupt_uart0();
 +#else
    serve_error_interrupt(&SD1);
 +#endif
    OSAL_IRQ_EPILOGUE();
  }
  #endif
 @@ -326,6 +376,30 @@ OSAL_IRQ_HANDLER(KINETIS_SERIAL2_ERROR_IRQ_VECTOR) {  }
  #endif
 +#if KINETIS_SERIAL_USE_UART3 || defined(__DOXYGEN__)
 +OSAL_IRQ_HANDLER(KINETIS_SERIAL3_ERROR_IRQ_VECTOR) {
 +  OSAL_IRQ_PROLOGUE();
 +  serve_error_interrupt(&SD4);
 +  OSAL_IRQ_EPILOGUE();
 +}
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART4 || defined(__DOXYGEN__)
 +OSAL_IRQ_HANDLER(KINETIS_SERIAL4_ERROR_IRQ_VECTOR) {
 +  OSAL_IRQ_PROLOGUE();
 +  serve_error_interrupt(&SD5);
 +  OSAL_IRQ_EPILOGUE();
 +}
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART5 || defined(__DOXYGEN__)
 +OSAL_IRQ_HANDLER(KINETIS_SERIAL5_ERROR_IRQ_VECTOR) {
 +  OSAL_IRQ_PROLOGUE();
 +  serve_error_interrupt(&SD6);
 +  OSAL_IRQ_EPILOGUE();
 +}
 +#endif
 +
  #endif /* KINETIS_HAS_SERIAL_ERROR_IRQ */
  /*===========================================================================*/
 @@ -341,19 +415,11 @@ void sd_lld_init(void) {  #if KINETIS_SERIAL_USE_UART0
    /* Driver initialization.*/
 -  sdObjectInit(&SD1, NULL, notify1);
  #if ! KINETIS_SERIAL0_IS_LPUART
 -  SD1.uart.bdh_p = &(UART0->BDH);
 -  SD1.uart.bdl_p = &(UART0->BDL);
 -  SD1.uart.c1_p =  &(UART0->C1);
 -  SD1.uart.c2_p =  &(UART0->C2);
 -  SD1.uart.c3_p =  &(UART0->C3);
 -  SD1.uart.c4_p =  &(UART0->C4);
 -  SD1.uart.s1_p =  (volatile uint8_t *)&(UART0->S1);
 -  SD1.uart.s2_p =  &(UART0->S2);
 -  SD1.uart.d_p =   &(UART0->D);
 +  sd_lld_init_driver(&SD1, UART0);
  #else /* ! KINETIS_SERIAL0_IS_LPUART */
    /* little endian! */
 +  sdObjectInit(&SD1, NULL, notify);
    SD1.uart.bdh_p = ((uint8_t *)&(LPUART0->BAUD)) + 1; /* BDH: BAUD, byte 3 */
    SD1.uart.bdl_p = ((uint8_t *)&(LPUART0->BAUD)) + 0; /* BDL: BAUD, byte 4 */
    SD1.uart.c1_p =  ((uint8_t *)&(LPUART0->CTRL)) + 0; /* C1: CTRL, byte 4 */
 @@ -377,20 +443,11 @@ void sd_lld_init(void) {  #if KINETIS_SERIAL_USE_UART1
    /* Driver initialization.*/
 -  sdObjectInit(&SD2, NULL, notify2);
  #if ! KINETIS_SERIAL1_IS_LPUART
 -  SD2.uart.bdh_p = &(UART1->BDH);
 -  SD2.uart.bdl_p = &(UART1->BDL);
 -  SD2.uart.c1_p =  &(UART1->C1);
 -  SD2.uart.c2_p =  &(UART1->C2);
 -  SD2.uart.c3_p =  &(UART1->C3);
 -  SD2.uart.c4_p =  &(UART1->C4);
 -  SD2.uart.s1_p =  (volatile uint8_t *)&(UART1->S1);
 -  SD2.uart.s2_p =  &(UART1->S2);
 -  SD2.uart.d_p =   &(UART1->D);
 -  SD2.uart.uart_p = UART1;
 +  sd_lld_init_driver(&SD2, UART1);
  #else /* ! KINETIS_SERIAL1_IS_LPUART */
    /* little endian! */
 +  sdObjectInit(&SD2, NULL, notify);
    SD2.uart.bdh_p = ((uint8_t *)&(LPUART1->BAUD)) + 1; /* BDH: BAUD, byte 3 */
    SD2.uart.bdl_p = ((uint8_t *)&(LPUART1->BAUD)) + 0; /* BDL: BAUD, byte 4 */
    SD2.uart.c1_p =  ((uint8_t *)&(LPUART1->CTRL)) + 0; /* C1: CTRL, byte 4 */
 @@ -406,19 +463,20 @@ void sd_lld_init(void) {  #endif /* KINETIS_SERIAL_USE_UART1 */
  #if KINETIS_SERIAL_USE_UART2
 -  /* Driver initialization.*/
 -  sdObjectInit(&SD3, NULL, notify3);
 -  SD3.uart.bdh_p = &(UART2->BDH);
 -  SD3.uart.bdl_p = &(UART2->BDL);
 -  SD3.uart.c1_p =  &(UART2->C1);
 -  SD3.uart.c2_p =  &(UART2->C2);
 -  SD3.uart.c3_p =  &(UART2->C3);
 -  SD3.uart.c4_p =  &(UART2->C4);
 -  SD3.uart.s1_p =  (volatile uint8_t *)&(UART2->S1);
 -  SD3.uart.s2_p =  &(UART2->S2);
 -  SD3.uart.d_p =   &(UART2->D);
 -  SD3.uart.uart_p = UART2;
 +  sd_lld_init_driver(&SD3, UART2);
  #endif /* KINETIS_SERIAL_USE_UART2 */
 +
 +#if KINETIS_SERIAL_USE_UART3
 +  sd_lld_init_driver(&SD4, UART3);
 +#endif /* KINETIS_SERIAL_USE_UART3 */
 +
 +#if KINETIS_SERIAL_USE_UART4
 +  sd_lld_init_driver(&SD5, UART4);
 +#endif /* KINETIS_SERIAL_USE_UART4 */
 +
 +#if KINETIS_SERIAL_USE_UART5
 +  sd_lld_init_driver(&SD6, UART5);
 +#endif /* KINETIS_SERIAL_USE_UART5 */
  }
  /**
 @@ -505,6 +563,33 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {      }
  #endif /* KINETIS_SERIAL_USE_UART2 */
 +#if KINETIS_SERIAL_USE_UART3
 +    if (sdp == &SD4) {
 +      SIM->SCGC4 |= SIM_SCGC4_UART3;
 +      configure_uart(sdp, config);
 +      nvicEnableVector(UART3Status_IRQn, KINETIS_SERIAL_UART3_PRIORITY);
 +      nvicEnableVector(UART3Error_IRQn, KINETIS_SERIAL_UART3_PRIORITY);
 +    }
 +#endif /* KINETIS_SERIAL_USE_UART3 */
 +
 +#if KINETIS_SERIAL_USE_UART4
 +    if (sdp == &SD5) {
 +      SIM->SCGC1 |= SIM_SCGC1_UART4;
 +      configure_uart(sdp, config);
 +      nvicEnableVector(UART4Status_IRQn, KINETIS_SERIAL_UART4_PRIORITY);
 +      nvicEnableVector(UART4Error_IRQn, KINETIS_SERIAL_UART4_PRIORITY);
 +    }
 +#endif /* KINETIS_SERIAL_USE_UART4 */
 +
 +#if KINETIS_SERIAL_USE_UART5
 +    if (sdp == &SD6) {
 +      SIM->SCGC1 |= SIM_SCGC1_UART5;
 +      configure_uart(sdp, config);
 +      nvicEnableVector(UART5Status_IRQn, KINETIS_SERIAL_UART5_PRIORITY);
 +      nvicEnableVector(UART5Error_IRQn, KINETIS_SERIAL_UART5_PRIORITY);
 +    }
 +#endif /* KINETIS_SERIAL_USE_UART5 */
 +
    }
    /* Configures the peripheral.*/
 @@ -575,6 +660,30 @@ void sd_lld_stop(SerialDriver *sdp) {        SIM->SCGC4 &= ~SIM_SCGC4_UART2;
      }
  #endif
 +
 +#if KINETIS_SERIAL_USE_UART3
 +    if (sdp == &SD4) {
 +      nvicDisableVector(UART3Status_IRQn);
 +      nvicDisableVector(UART3Error_IRQn);
 +      SIM->SCGC4 &= ~SIM_SCGC4_UART3;
 +    }
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART4
 +    if (sdp == &SD5) {
 +      nvicDisableVector(UART4Status_IRQn);
 +      nvicDisableVector(UART4Error_IRQn);
 +      SIM->SCGC1 &= ~SIM_SCGC1_UART4;
 +    }
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART5
 +    if (sdp == &SD6) {
 +      nvicDisableVector(UART5Status_IRQn);
 +      nvicDisableVector(UART5Error_IRQn);
 +      SIM->SCGC1 &= ~SIM_SCGC1_UART5;
 +    }
 +#endif
    }
  }
 diff --git a/os/hal/ports/KINETIS/LLD/hal_serial_lld.h b/os/hal/ports/KINETIS/LLD/hal_serial_lld.h index f11c063..3cb6d2b 100644 --- a/os/hal/ports/KINETIS/LLD/hal_serial_lld.h +++ b/os/hal/ports/KINETIS/LLD/hal_serial_lld.h @@ -60,6 +60,27 @@  #if !defined(KINETIS_SERIAL_USE_UART2) || defined(__DOXYGEN__)
  #define KINETIS_SERIAL_USE_UART2             FALSE
  #endif
 +/**
 + * @brief   SD4 driver enable switch.
 + * @details If set to @p TRUE the support for SD4 is included.
 + */
 +#if !defined(KINETIS_SERIAL_USE_UART3) || defined(__DOXYGEN__)
 +#define KINETIS_SERIAL_USE_UART3             FALSE
 +#endif
 +/**
 + * @brief   SD5 driver enable switch.
 + * @details If set to @p TRUE the support for SD5 is included.
 + */
 +#if !defined(KINETIS_SERIAL_USE_UART4) || defined(__DOXYGEN__)
 +#define KINETIS_SERIAL_USE_UART4             FALSE
 +#endif
 +/**
 + * @brief   SD6 driver enable switch.
 + * @details If set to @p TRUE the support for SD6 is included.
 + */
 +#if !defined(KINETIS_SERIAL_USE_UART5) || defined(__DOXYGEN__)
 +#define KINETIS_SERIAL_USE_UART5             FALSE
 +#endif
  /**
   * @brief   UART0 interrupt priority level setting.
 @@ -83,6 +104,27 @@  #endif
  /**
 + * @brief   UART3 interrupt priority level setting.
 + */
 +#if !defined(KINETIS_SERIAL_UART3_PRIORITY) || defined(__DOXYGEN__)
 +#define KINETIS_SERIAL_UART3_PRIORITY        12
 +#endif
 +
 +/**
 + * @brief   UART4 interrupt priority level setting.
 + */
 +#if !defined(KINETIS_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__)
 +#define KINETIS_SERIAL_UART4_PRIORITY        12
 +#endif
 +
 +/**
 + * @brief   UART5 interrupt priority level setting.
 + */
 +#if !defined(KINETIS_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__)
 +#define KINETIS_SERIAL_UART5_PRIORITY        12
 +#endif
 +
 +/**
   * @brief   UART0 clock source.
   */
  #if !defined(KINETIS_UART0_CLOCK_SRC) || defined(__DOXYGEN__)
 @@ -115,8 +157,21 @@  #error "UART2 not present in the selected device"
  #endif
 +#if KINETIS_SERIAL_USE_UART3 && !KINETIS_HAS_SERIAL3
 +#error "UART3 not present in the selected device"
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART4 && !KINETIS_HAS_SERIAL4
 +#error "UART4 not present in the selected device"
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART5 && !KINETIS_HAS_SERIAL5
 +#error "UART5 not present in the selected device"
 +#endif
 +
  #if !(KINETIS_SERIAL_USE_UART0 || KINETIS_SERIAL_USE_UART1 || \
 -      KINETIS_SERIAL_USE_UART2)
 +      KINETIS_SERIAL_USE_UART2 || KINETIS_SERIAL_USE_UART3 || \
 +      KINETIS_SERIAL_USE_UART4 || KINETIS_SERIAL_USE_UART5)
  #error "Serial driver activated but no UART peripheral assigned"
  #endif
 @@ -203,6 +258,18 @@ extern SerialDriver SD2;  extern SerialDriver SD3;
  #endif
 +#if KINETIS_SERIAL_USE_UART3 && !defined(__DOXYGEN__)
 +extern SerialDriver SD4;
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART4 && !defined(__DOXYGEN__)
 +extern SerialDriver SD5;
 +#endif
 +
 +#if KINETIS_SERIAL_USE_UART5 && !defined(__DOXYGEN__)
 +extern SerialDriver SD6;
 +#endif
 +
  #ifdef __cplusplus
  extern "C" {
  #endif
 | 
