Beispiel #1
0
/**
 * @brief   Write data to NAND.
 *
 * @param[in] nandp         pointer to the @p NANDDriver object
 * @param[in] data          buffer with data to be written
 * @param[in] datalen       size of data buffer
 * @param[in] addr          pointer to address buffer
 * @param[in] addrlen       length of address
 * @param[out] ecc          pointer to store computed ECC. Ignored when NULL.
 *
 * @return    The operation status reported by NAND IC (0x70 command).
 *
 * @notapi
 */
uint8_t nand_lld_write_data(NANDDriver *nandp, const uint8_t *data,
                size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc) {

  nandp->state = NAND_WRITE;

  nand_lld_write_cmd (nandp, NAND_CMD_WRITE);
  osalSysLock();
  nand_lld_write_addr(nandp, addr, addrlen);

  /* Now start DMA transfer to NAND buffer and put thread in sleep state.
     Tread will be woken up from ready ISR. */
  nandp->state = NAND_DMA_TX;
  osalDbgAssert((nandp->nand->PCR & FSMC_PCR_ECCEN) == 0,
          "State machine broken. ECCEN must be previously disabled.");

  if (NULL != ecc){
    nandp->nand->PCR |= FSMC_PCR_ECCEN;
  }

  dmaStartMemCopy(nandp->dma, nandp->dmamode, data, nandp->map_data, datalen);

  nand_lld_suspend_thread(nandp);
  osalSysUnlock();

  if (NULL != ecc){
    while (! (nandp->nand->SR & FSMC_SR_FEMPT))
      ;
    *ecc = nandp->nand->ECCR;
    nandp->nand->PCR &= ~FSMC_PCR_ECCEN;
  }

  return nand_lld_read_status(nandp);
}
Beispiel #2
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();
}
Beispiel #3
0
/*
 * Application entry point.
 */
int main(void) {
  unsigned i;
  static uint8_t patterns1[4096], patterns2[4096], buf1[4096], buf2[4096];

  /* System initializations.
     - HAL initialization, this also initializes the configured device drivers
       and performs the board-specific initializations.
     - Kernel initialization, the main() function becomes a thread and the
       RTOS is active.*/
  halInit();
  chSysInit();

  /* Creates the blinker thread.*/
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 10,
                    Thread1, NULL);

  /* Activates the ADC1 driver and the temperature sensor.*/
  adcStart(&ADCD1, NULL);
  adcSTM32EnableTSVREFE();

  /* Starts an ADC continuous conversion and its watchdog virtual timer.*/
  chVTSet(&adcvt, MS2ST(10), tmo, (void *)"ADC timeout");
  adcStartConversion(&ADCD1, &adcgrpcfg2, samples2, ADC_GRP2_BUF_DEPTH);

  /* Activating SPI drivers.*/
  spiStart(&SPID1, &hs_spicfg);
  spiStart(&SPID2, &hs_spicfg);
  spiStart(&SPID3, &hs_spicfg);

  /* Starting SPI threads instances.*/
  chThdCreateStatic(waSPI1, sizeof(waSPI1), NORMALPRIO + 1, spi_thread, &SPID1);
  chThdCreateStatic(waSPI2, sizeof(waSPI2), NORMALPRIO + 1, spi_thread, &SPID2);
  chThdCreateStatic(waSPI3, sizeof(waSPI3), NORMALPRIO + 1, spi_thread, &SPID3);

  /* Allocating two DMA2 streams for memory copy operations.*/
  if (dmaStreamAllocate(STM32_DMA2_STREAM6, 0, NULL, NULL))
    chSysHalt("DMA already in use");
  if (dmaStreamAllocate(STM32_DMA2_STREAM7, 0, NULL, NULL))
    chSysHalt("DMA already in use");
  for (i = 0; i < sizeof (patterns1); i++)
    patterns1[i] = (uint8_t)i;
  for (i = 0; i < sizeof (patterns2); i++)
    patterns2[i] = (uint8_t)(i ^ 0xAA);

  /* Normal main() thread activity, it does continues memory copy operations
     using 2 DMA streams at the lowest priority.*/
  while (true) {
    virtual_timer_t vt;

    chVTObjectInit(&vt);

    /* Starts a VT working as watchdog to catch a malfunction in the DMA
       driver.*/
    chVTSet(&vt, MS2ST(10), tmo, (void *)"copy timeout");

    /* Copy pattern 1.*/
    dmaStartMemCopy(STM32_DMA2_STREAM6,
                    STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_BYTE |
                                         STM32_DMA_CR_MSIZE_BYTE,
                    patterns1, buf1, sizeof (patterns1));
    dmaStartMemCopy(STM32_DMA2_STREAM7,
                    STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_BYTE |
                                         STM32_DMA_CR_MSIZE_BYTE,
                    patterns1, buf2, sizeof (patterns1));
    dmaWaitCompletion(STM32_DMA2_STREAM6);
    dmaWaitCompletion(STM32_DMA2_STREAM7);
    if (memcmp(patterns1, buf1, sizeof (patterns1)))
      chSysHalt("pattern error");
    if (memcmp(patterns1, buf2, sizeof (patterns1)))
      chSysHalt("pattern error");

    /* Copy pattern 2.*/
    dmaStartMemCopy(STM32_DMA2_STREAM6,
                    STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_BYTE |
                                         STM32_DMA_CR_MSIZE_BYTE,
                    patterns2, buf1, sizeof (patterns2));
    dmaStartMemCopy(STM32_DMA2_STREAM7,
                    STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_BYTE |
                                         STM32_DMA_CR_MSIZE_BYTE,
                    patterns2, buf2, sizeof (patterns2));
    dmaWaitCompletion(STM32_DMA2_STREAM6);
    dmaWaitCompletion(STM32_DMA2_STREAM7);
    if (memcmp(patterns2, buf1, sizeof (patterns2)))
      chSysHalt("pattern error");
    if (memcmp(patterns2, buf2, sizeof (patterns2)))
      chSysHalt("pattern error");

    /* Stops the watchdog.*/
    chVTReset(&vt);

    chThdSleepMilliseconds(2);
  }
  return 0;
}