Exemplo n.º 1
0
/**
 * @brief   Ready interrupt handler
 *
 * @param[in] nandp    pointer to the @p NANDDriver object
 *
 * @notapi
 */
static void nand_isr_handler (NANDDriver *nandp) {

  osalSysLockFromISR();

#if !STM32_NAND_USE_EXT_INT
  osalDbgCheck(nandp->nand->SR & FSMC_SR_IRS); /* spurious interrupt happened */
  nandp->nand->SR &= ~FSMC_SR_IRS;
#endif

  switch (nandp->state){
  case NAND_READ:
    nandp->state = NAND_DMA_RX;
    dmaStartMemCopy(nandp->dma, nandp->dmamode,
                    nandp->map_data, nandp->rxdata, nandp->datalen);
    /* thread will be waked up from DMA ISR */
    break;

  case NAND_ERASE:
    /* NAND reports about erase finish */
    nandp->state = NAND_READY;
    wakeup_isr(nandp);
    break;

  case NAND_PROGRAM:
    /* NAND reports about page programming finish */
    nandp->state = NAND_READY;
    wakeup_isr(nandp);
    break;

  default:
    osalSysHalt("Unhandled case");
    break;
  }
  osalSysUnlockFromISR();
}
Exemplo n.º 2
0
/**
 * @brief   I2C shared ISR code.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 *
 * @notapi
 */
static void i2c_lld_serve_interrupt(I2CDriver *i2cp) {

  uint32_t sr;
  sr = AT91C_BASE_TWI->TWI_SR;
  /* this masking doing in official Atmel driver. Is it needed ??? */
  sr &= AT91C_BASE_TWI->TWI_IMR;

  if (sr & AT91C_TWI_NACK){
    i2cp->errors |= I2CD_ACK_FAILURE;
    wakeup_isr(i2cp, RDY_RESET);
    return;
  }
  if (sr & AT91C_TWI_RXRDY){
    _i2c_lld_serve_rx_interrupt(i2cp);
  }
  else if (sr & AT91C_TWI_TXRDY){
    _i2c_lld_serve_tx_interrupt(i2cp);
  }
  else if (sr & AT91C_TWI_TXCOMP){
    AT91C_BASE_TWI->TWI_IDR = AT91C_TWI_TXCOMP;
    wakeup_isr(i2cp, RDY_OK);
  }
  else
    chDbgPanic("Invalid value");
}
Exemplo n.º 3
0
void i2c_lld_serve_interrupt(I2CDriver *i2cp) {
  UNUSED(i2cp);
  bscdevice_t *device = i2cp->device;
  uint32_t status = device->status;

  if (status & (BSC_CLKT | BSC_ERR)) {
    // TODO set error flags
    wakeup_isr(i2cp, RDY_RESET);
  }
  else if (status & BSC_DONE) {
    while ((status & BSC_RXD) && (i2cp->rxidx < i2cp->rxbytes))
      i2cp->rxbuf[i2cp->rxidx++] = device->dataFifo;
    device->control = 0;
    device->status = BSC_CLKT | BSC_ERR | BSC_DONE;
    wakeup_isr(i2cp, RDY_OK);
  }
  else if (status & BSC_TXW) {
    while ((i2cp->txidx < i2cp->txbytes) && (status & BSC_TXD))
      device->dataFifo = i2cp->txbuf[i2cp->txidx++];
  }
  else if (status & BSC_RXR) {
    while ((i2cp->rxidx < i2cp->rxbytes) && (status & BSC_RXD))
      i2cp->rxbuf[i2cp->rxidx++] = device->dataFifo;
  }
}
Exemplo n.º 4
0
/**
 * @brief   I2C shared ISR code.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 *
 * @notapi
 */
static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
  I2C_TypeDef *dp = i2cp->i2c;

  /* Interrupts are disabled just before dmaStreamEnable() because there
     is no need of interrupts until next transaction begin. All the work is
     done by the DMA.*/
  switch (i2c_get_event(i2cp)) {
  case I2C_EV5_MASTER_MODE_SELECT:
    dp->DR = i2cp->addr;
    break;
  case I2C_EV6_MASTER_REC_MODE_SELECTED:
    dp->CR2 &= ~I2C_CR2_ITEVTEN;
    dmaStreamEnable(i2cp->dmarx);
    dp->CR2 |= I2C_CR2_LAST;                 /* Needed in receiver mode. */
    break;
  case I2C_EV6_MASTER_TRA_MODE_SELECTED:
    dp->CR2 &= ~I2C_CR2_ITEVTEN;
    dmaStreamEnable(i2cp->dmatx);
    break;
  case I2C_EV8_2_MASTER_BYTE_TRANSMITTED:
    /* Catches BTF event after the end of transmission.*/
    if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) {
      /* Starts "read after write" operation, LSB = 1 -> receive.*/
      i2cp->addr |= 0x01;
      dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
      return;
    }
    dp->CR2 &= ~I2C_CR2_ITEVTEN;
    dp->CR1 |= I2C_CR1_STOP;
    wakeup_isr(i2cp, RDY_OK);
    break;
  default:
    break;
  }
}
Exemplo n.º 5
0
/**
 * @brief   DMA RX end IRQ handler.
 *
 * @param[in] nandp    pointer to the @p NANDDriver object
 * @param[in] flags    pre-shifted content of the ISR register
 *
 * @notapi
 */
static void nand_lld_serve_transfer_end_irq(NANDDriver *nandp, uint32_t flags) {
  /* DMA errors handling.*/
#if defined(STM32_NAND_DMA_ERROR_HOOK)
  if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
    STM32_NAND_DMA_ERROR_HOOK(nandp);
  }
#else
  (void)flags;
#endif

  osalSysLockFromISR();

  dmaStreamDisable(nandp->dma);

  switch (nandp->state){
  case NAND_DMA_TX:
    nandp->state = NAND_PROGRAM;
    nandp->map_cmd[0] = NAND_CMD_PAGEPROG;
    /* thread will be woken from ready_isr() */
    break;

  case NAND_DMA_RX:
    nandp->state = NAND_READY;
    nandp->rxdata = NULL;
    nandp->datalen = 0;
    wakeup_isr(nandp);
    break;

  default:
    osalSysHalt("Unhandled case");
    break;
  }

  osalSysUnlockFromISR();
}
Exemplo n.º 6
0
/**
 * @brief   I2C shared ISR code.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 * @param[in] isr       content of the ISR register to be decoded
 *
 * @notapi
 */
static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) {
  I2C_TypeDef *dp = i2cp->i2c;

  if ((isr & I2C_ISR_TC) && (i2cp->state == I2C_ACTIVE_TX)) {
    size_t rxbytes;

    /* Make sure no more 'Transfer complete' interrupts.*/
    dp->CR1 &= ~I2C_CR1_TCIE;

    rxbytes = dmaStreamGetTransactionSize(i2cp->dmarx);
    if (rxbytes > 0) {
      i2cp->state = I2C_ACTIVE_RX;

      /* Enable RX DMA */
      dmaStreamEnable(i2cp->dmarx);

      dp->CR2 &= ~I2C_CR2_NBYTES;
      dp->CR2 |= rxbytes << 16;

      /* Starts the read operation.*/
      dp->CR2 |= I2C_CR2_RD_WRN;
      dp->CR2 |= I2C_CR2_START;
    }
    else {
      /* Nothing to receive - send STOP immediately.*/
      dp->CR2 |= I2C_CR2_STOP;
    }
  }
  if (isr & I2C_ISR_NACKF) {
    /* Starts a STOP sequence immediately on error.*/
    dp->CR2 |= I2C_CR2_STOP;

    i2cp->errors |= I2CD_ACK_FAILURE;
  }
  if (isr & I2C_ISR_STOPF) {
    /* Stops the associated DMA streams.*/
    dmaStreamDisable(i2cp->dmatx);
    dmaStreamDisable(i2cp->dmarx);

    if (i2cp->errors) {
      wakeup_isr(i2cp, RDY_RESET);
    }
    else {
      wakeup_isr(i2cp, RDY_OK);
    }
  }
}
Exemplo n.º 7
0
void serve_i2c_interrupt(I2CDriver *i2cp) {
    i2cdef_t i2c = i2cp->i2c;
    uint32_t status = i2c->TWI_SR;
    msg_t msg;

    if (status & TWI_SR_ENDRX) {
        palTogglePad(IOPORTA, 21);

        /* Disable PDC */
        i2c->TWI_PTCR = TWI_PTCR_RXTDIS;
        i2c->TWI_IDR = TWI_IDR_ENDRX;


        /* Wait for RX ready flag */
        while (1) {
            status = i2c->TWI_SR;
            if (status & TWI_SR_RXRDY) {
                break;
            }
        }

        /* Complete the transfer. */
        i2c->TWI_CR = TWI_CR_STOP;
        /* Read second last data */
        *i2cp->curbuf++ = i2c->TWI_RHR;

        /* Wait for RX ready flag */
        while (1) {
            status = i2c->TWI_SR;
            if (status & TWI_SR_RXRDY) {
                break;
            }
        }

        /* Read last data */
        *i2cp->curbuf++ = i2c->TWI_RHR;
        /* Wait for TX complete flag before releasing semaphore */
        while (1) {
            status = i2c->TWI_SR;
            if (status & TWI_SR_TXCOMP) {
                break;
            }
        }

        msg = RDY_OK;
    } else if (status & (TWI_SR_NACK | TWI_SR_OVRE)) {
        msg = RDY_RESET;
        i2cp->errors = status;
    }
    wakeup_isr(i2cp, msg);
}
Exemplo n.º 8
0
/**
 * @brief   I2C error handler.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 *
 * @notapi
 */
static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp) {
  I2C_TypeDef *dp = i2cp->i2c;
  i2cflags_t errors;

  /* Clears interrupt flags just to be safe.*/
  chSysLockFromIsr();
  dmaStreamDisable(i2cp->dmatx);
  dmaStreamDisable(i2cp->dmarx);
  chSysUnlockFromIsr();

  errors = I2CD_NO_ERROR;

  if (dp->SR1 & I2C_SR1_BERR) {                     /* Bus error.           */
    dp->SR1 &= ~I2C_SR1_BERR;
    errors |= I2CD_BUS_ERROR;
  }
  if (dp->SR1 & I2C_SR1_ARLO) {                     /* Arbitration lost.    */
    dp->SR1 &= ~I2C_SR1_ARLO;
    errors |= I2CD_ARBITRATION_LOST;
  }
  if (dp->SR1 & I2C_SR1_AF) {                       /* Acknowledge fail.    */
    dp->SR1 &= ~I2C_SR1_AF;
    dp->CR2 &= ~I2C_CR2_ITEVTEN;
    dp->CR1 |= I2C_CR1_STOP;                        /* Setting stop bit.    */
    errors |= I2CD_ACK_FAILURE;
  }
  if (dp->SR1 & I2C_SR1_OVR) {                      /* Overrun.             */
    dp->SR1 &= ~I2C_SR1_OVR;
    errors |= I2CD_OVERRUN;
  }
  if (dp->SR1 & I2C_SR1_PECERR) {                   /* PEC error.           */
    dp->SR1 &= ~I2C_SR1_PECERR;
    errors |= I2CD_PEC_ERROR;
  }
  if (dp->SR1 & I2C_SR1_TIMEOUT) {                  /* SMBus Timeout.       */
    dp->SR1 &= ~I2C_SR1_TIMEOUT;
    errors |= I2CD_TIMEOUT;
  }
  if (dp->SR1 & I2C_SR1_SMBALERT) {                 /* SMBus alert.         */
    dp->SR1 &= ~I2C_SR1_SMBALERT;
    errors |= I2CD_SMB_ALERT;
  }

  /* If some error has been identified then sends wakes the waiting thread.*/
  if (errors != I2CD_NO_ERROR) {
    i2cp->errors = errors;
    wakeup_isr(i2cp, RDY_RESET);
  }
}
Exemplo n.º 9
0
/**
 * @brief   DMA RX end IRQ handler.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 * @param[in] flags     pre-shifted content of the ISR register
 *
 * @notapi
 */
static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) {
  I2C_TypeDef *dp = i2cp->i2c;

  /* DMA errors handling.*/
#if defined(STM32_I2C_DMA_ERROR_HOOK)
  if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
    STM32_I2C_DMA_ERROR_HOOK(i2cp);
  }
#else
  (void)flags;
#endif

  dmaStreamDisable(i2cp->dmarx);
  dp->CR2 |= I2C_CR2_STOP;
  wakeup_isr(i2cp, RDY_OK);
}
Exemplo n.º 10
0
/**
 * @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);
}
Exemplo n.º 11
0
/**
 * @brief   I2C error handler.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 * @param[in] isr       content of the ISR register to be decoded
 *
 * @notapi
 */
static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) {

  /* Clears interrupt flags just to be safe.*/
  dmaStreamDisable(i2cp->dmatx);
  dmaStreamDisable(i2cp->dmarx);

  if (isr & I2C_ISR_BERR)
    i2cp->errors |= I2CD_BUS_ERROR;

  if (isr & I2C_ISR_ARLO)
    i2cp->errors |= I2CD_ARBITRATION_LOST;

  if (isr & I2C_ISR_OVR)
    i2cp->errors |= I2CD_OVERRUN;

  if (isr & I2C_ISR_TIMEOUT)
    i2cp->errors |= I2CD_TIMEOUT;

  /* If some error has been identified then sends wakes the waiting thread.*/
  if (i2cp->errors != I2CD_NO_ERROR)
    wakeup_isr(i2cp, RDY_RESET);
}
Exemplo n.º 12
0
/**
 * @brief   I2C error handler.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 * @param[in]  sr       content of the SR1 register to be decoded
 *
 * @notapi
 */
static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) {

  /* Clears interrupt flags just to be safe.*/
  dmaStreamDisable(i2cp->dmatx);
  dmaStreamDisable(i2cp->dmarx);

  i2cp->errors = I2CD_NO_ERROR;

  if (sr & I2C_SR1_BERR)                            /* Bus error.           */
    i2cp->errors |= I2CD_BUS_ERROR;

  if (sr & I2C_SR1_ARLO)                            /* Arbitration lost.    */
    i2cp->errors |= I2CD_ARBITRATION_LOST;

  if (sr & I2C_SR1_AF) {                            /* Acknowledge fail.    */
    i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN;
    i2cp->i2c->CR1 |= I2C_CR1_STOP;                 /* Setting stop bit.    */
    i2cp->errors |= I2CD_ACK_FAILURE;
  }

  if (sr & I2C_SR1_OVR)                             /* Overrun.             */
    i2cp->errors |= I2CD_OVERRUN;

  if (sr & I2C_SR1_TIMEOUT)                         /* SMBus Timeout.       */
    i2cp->errors |= I2CD_TIMEOUT;

  if (sr & I2C_SR1_PECERR)                          /* PEC error.           */
    i2cp->errors |= I2CD_PEC_ERROR;

  if (sr & I2C_SR1_SMBALERT)                        /* SMBus alert.         */
    i2cp->errors |= I2CD_SMB_ALERT;

  /* If some error has been identified then sends wakes the waiting thread.*/
  if (i2cp->errors != I2CD_NO_ERROR)
    wakeup_isr(i2cp, RDY_RESET);
}