فهرست منبع

Driver NAND usage examples enhanced

Vladimir Umek 8 سال پیش
والد
کامیت
50009d85ab
1فایلهای تغییر یافته به همراه145 افزوده شده و 53 حذف شده
  1. 145 53
      CMSIS/DoxyGen/Driver/src/NAND_Demo.c

+ 145 - 53
CMSIS/DoxyGen/Driver/src/NAND_Demo.c

@@ -1,73 +1,165 @@
 #include "Driver_NAND.h"
-  
-// NAND driver instance
-extern ARM_DRIVER_NAND Driver_NAND0;
-extern ARM_DRIVER_NAND * nandDev = &Driver_NAND0;
- 
-static void SendAddress (ARM_DRIVER_NAND *drv, uint32_t dev_num, uint32_t addr, uint32_t cycles)
-{
-  while (cycles--) {
-    drv->SendAddress (dev_num, (uint8_t)addr);
-    addr >>= 8U;
+ 
+/* ONFI commands */
+#define ONFI_CMD_READ_1ST               0x00   ///< Read 1st Cycle
+#define ONFI_CMD_PROGRAM_2ND            0x10   ///< Page Program 2nd Cycle
+#define ONFI_CMD_READ_2ND               0x30   ///< Read 2nd Cycle
+#define ONFI_CMD_PROGRAM_1ST            0x80   ///< Page Program 1st Cycle
+#define ONFI_CMD_RESET                  0xFF   ///< Reset Command
+ 
+/* NAND Signal Event callback function */
+volatile uint32_t NAND_Events;
+void NAND_SignalEventCallback (uint32_t dev_num, uint32_t event) {
+  if (dev_num == 0) {
+    NAND_Events |= event;
+  }
+  else {
+    // ..
   }
 }
  
-int main (void)
-{
-  /* Query drivers capabilities */
-  const ARM_NAND_CAPABILITIES capabilities = nandDev->GetCapabilities();
- 
-  /* Initialize NAND device */
-  nandDev->Initialize (NULL);
-  
-  /* Power-on NAND device */
-  nandDev->PowerControl (ARM_POWER_FULL);
-  
-  /* Turn ON device power */
+/* NAND device Power ON */
+void PowerOn (ARM_DRIVER_NAND *drv, uint32_t dev_num) {
+  ARM_NAND_CAPABILITIES capabilities;
+ 
+  // Query drivers capabilities
+  capabilities = drv->GetCapabilities();
+ 
+  // Initialize NAND device
+  drv->Initialize (NAND_SignalEventCallback);
+ 
+  // Power-on NAND driver
+  drv->PowerControl (ARM_POWER_FULL);
+ 
+  // Turn ON device power
   uint32_t volt = 0U;
+ 
   if (capabilities.vcc)      { volt |= ARM_NAND_POWER_VCC_3V3;  }
   if (capabilities.vcc_1v8)  { volt |= ARM_NAND_POWER_VCC_1V8;  }
   if (capabilities.vccq)     { volt |= ARM_NAND_POWER_VCCQ_3V3; }
   if (capabilities.vccq_1v8) { volt |= ARM_NAND_POWER_VCCQ_1V8; }
-  
+ 
   if (volt != 0U) {  
-    nandDev->DevicePower (volt);
+    drv->DevicePower (volt);
   }
-  
-  /* Setting bus mode */
-  nandDev->Control (0U, ARM_NAND_BUS_MODE, ARM_NAND_BUS_SDR);
-  
-  /* Setting bus data width */
-  nandDev->Control (0U, ARM_NAND_BUS_DATA_WIDTH, ARM_NAND_BUS_DATA_WIDTH_8);
-
-  /* Enable chip manually if needed */
+ 
+  // Setting bus mode
+  drv->Control (0U, ARM_NAND_BUS_MODE, ARM_NAND_BUS_SDR);
+ 
+  // Setting bus data width
+  drv->Control (0U, ARM_NAND_BUS_DATA_WIDTH, ARM_NAND_BUS_DATA_WIDTH_8);
+ 
+  // Enable chip manually if needed
   if (capabilities.ce_manual) {
-    nandDev->ChipEnable (0U, true);
+    drv->ChipEnable (dev_num, true);
   }
-  
-  /* Send ONFI Read command */
-  nandDev->SendCommand (0U, 0x00U);
-  
-  /* Send address, LSB first */
-  SendAddress (nandDev, 0U, 0x0100U, 2U);
-  SendAddress (nandDev, 0U, 0x0047U, 2U);
-  
-  /* Read some data */
-  uint8_t buf[256];
-  nandDev->ReadData (0U, buf, sizeof(buf)/sizeof(buf[0]), 0U);
-  
-  /* Disable chip manually if needed */
+ 
+  // Send ONFI Reset command */
+  drv->SendCommand (dev_num, ONFI_CMD_RESET);
+}
+ 
+/* NAND device Power OFF */
+void PowerOff (ARM_DRIVER_NAND *drv, uint32_t dev_num) {
+  ARM_NAND_CAPABILITIES capabilities;
+ 
+  // Query drivers capabilities
+  capabilities = drv->GetCapabilities();
+ 
+  // Disable chip manually if needed
   if (capabilities.ce_manual) {
-    nandDev->ChipEnable (0U, false);
+    drv->ChipEnable (0U, false);
   }
-  
-  /* Switch off gracefully */
-  volt = 0U;
+ 
+  // Switch OFF gracefully
+  uint32_t volt = 0U;
+ 
   if (capabilities.vcc)  { volt |= ARM_NAND_POWER_VCC_OFF;  }
   if (capabilities.vccq) { volt |= ARM_NAND_POWER_VCCQ_OFF; }
   if (volt) {
-    nandDev->DevicePower (volt);
+    drv->DevicePower (volt);
   }
-  nandDev->PowerControl (ARM_POWER_OFF);
-  nandDev->Uninitialize ();
+  drv->PowerControl (ARM_POWER_OFF);
+  drv->Uninitialize ();
+}
+ 
+/* Read NAND page. */
+void ReadPage (ARM_DRIVER_NAND *drv, uint32_t row, uint8_t *data, uint32_t cnt) {
+  uint32_t dev_num = 0;   // Device number
+  uint32_t mode;
+ 
+  // Send Read 1st command
+  drv->SendCommand (dev_num, ONFI_CMD_READ_1ST);
+ 
+  // Send address (column: 2 cycles, row: 3 cycles)
+  drv->SendAddress (dev_num, 0x00);
+  drv->SendAddress (dev_num, 0x00);
+  drv->SendAddress (dev_num, (uint8_t)(row));
+  drv->SendAddress (dev_num, (uint8_t)(row >>  8));
+  drv->SendAddress (dev_num, (uint8_t)(row >> 16));
+ 
+  // Send Read 2nd command
+  drv->SendCommand (dev_num, ONFI_CMD_READ_2ND);
+ 
+  // Wait until device ready
+  while (drv->GetDeviceBusy(dev_num) == 1) { ; }
+ 
+  // Use ECC algorithm number 2, ECC0 (ECC over main+spare)
+  mode = ARM_NAND_ECC(2) | ARM_NAND_ECC0;
+ 
+  // Transfer data from the NAND chip
+  if (drv->ReadData (dev_num, data, cnt, mode | ARM_NAND_DRIVER_DONE_EVENT) != cnt) {
+    // Wait until driver done event received
+    while ((NAND_Events & ARM_NAND_DRIVER_DONE_EVENT) == 0) { ; }
+    // Read page completed
+ 
+    if ((NAND_Events & ARM_NAND_EVENT_ECC_ERROR) != 0) {
+      // ECC correction failed
+    }
+  }
+}
+ 
+/* Write NAND page (ExecuteSequence interface). */
+void WritePage_Seq (ARM_DRIVER_NAND *drv, uint32_t row, const uint8_t *data, uint32_t cnt) {
+  uint32_t dev_num = 0;   // Device number
+  uint32_t cmd;
+  uint32_t code;
+  uint32_t seq;
+ 
+  // Prepare commands to send
+  cmd = ONFI_CMD_PROGRAM_1ST | (ONFI_CMD_PROGRAM_2ND << 8);
+ 
+  // Construct sequence code:
+  // - Send command 1
+  // - Send 2 cycles of column address and 3 cycles of row address
+  // - Write data from memory to device
+  // - Send command 2
+  code = ARM_NAND_CODE_SEND_CMD1      |
+         ARM_NAND_CODE_SEND_ADDR_COL1 |
+         ARM_NAND_CODE_SEND_ADDR_COL2 |
+         ARM_NAND_CODE_SEND_ADDR_ROW1 |
+         ARM_NAND_CODE_SEND_ADDR_ROW2 |
+         ARM_NAND_CODE_SEND_ADDR_ROW3 |
+         ARM_NAND_CODE_WRITE_DATA     |
+         ARM_NAND_CODE_SEND_CMD2      ;
+ 
+  // - Use ECC algorithm number 2, ECC0 (ECC over main+spare)
+  code |= ARM_NAND_ECC(2) | ARM_NAND_ECC0;
+ 
+  // Number of iterations in a sequence
+  seq = 1;
+ 
+  drv->ExecuteSequence (dev_num,        // Device number
+                        code,           // Sequence code
+                        cmd,            // Command(s)
+                        0,              // Column address
+                        row,            // Row address
+                        (void *)data,   // Data buffer
+                        cnt,            // Number of data items (per iteration)
+                        NULL,           // Device status will not be read
+                        &seq);          // Number of iterations
+ 
+  // Wait until done
+  while (drv->GetStatus(dev_num).busy != 0) { ; }
+ 
+  // Page write completed
 }