static int nor_write(mtd_t *_dev, void *_src, uint32_t _off, int _amt) { nor_device_t *dev = nor_device_get(_dev); int startSector = _off / NOR_BLOCK_SIZE; int endSector = (_off + _amt) / NOR_BLOCK_SIZE; int numSectors = endSector - startSector + 1; uint8_t* sectorsToChange = (uint8_t*) malloc(NOR_BLOCK_SIZE * numSectors); nor_read(_dev, sectorsToChange, startSector * NOR_BLOCK_SIZE, NOR_BLOCK_SIZE * numSectors); int offsetFromStart = _off - (startSector * NOR_BLOCK_SIZE); memcpy(sectorsToChange + offsetFromStart, _src, _amt); int i; for(i = 0; i < numSectors; i++) { if(nor_erase_sector(dev, (i + startSector) * NOR_BLOCK_SIZE) != 0) return -1; int j; uint16_t* curSector = (uint16_t*)(sectorsToChange + (i * NOR_BLOCK_SIZE)); for(j = 0; j < NOR_BLOCK_SIZE; j += 2) { if(nor_write_short(dev, ((i + startSector) * NOR_BLOCK_SIZE) + j, curSector[j/2]) != 0) return -1; } } free(sectorsToChange); return 0; }
void images_erase(Image* image) { if(image == NULL) return; nor_erase_sector(image->offset); images_release(); images_setup(); }
void cmd_nor_erase(int argc, char** argv) { if(argc < 3) { bufferPrintf("Usage: %s <address> <address again for confirmation>\r\n", argv[0]); return; } uint32_t addr1 = parseNumber(argv[1]); uint32_t addr2 = parseNumber(argv[2]); if(addr1 != addr2) { bufferPrintf("0x%x does not match 0x%x\r\n", addr1, addr2); return; } bufferPrintf("Erasing 0x%x - 0x%x...\r\n", addr1, addr1 + getNORSectorSize()); nor_erase_sector(addr1); bufferPrintf("Done.\r\n"); }
int main(void) { SetupHardware(); sei(); // Initialize the USB, and then wait for the host to set configuration. // If the Teensy is powered without a PC connected to the USB port, // this will wait forever. while (USB_DeviceState != DEVICE_STATE_Configured) /* wait */ USB_USBTask(); //configure all i/o lines (and set tristate=low) //nor_initports(); nand_initports(); // Wait an extra second for the PC's operating system to load drivers // and do whatever it does to actually be ready for input _delay_ms(1000); usbio_initbuffers(); int16_t command = -1; uint8_t nand_id = 0; uint16_t nand_block = 0; while (1) { USB_USBTask(); while (USB_DeviceState == DEVICE_STATE_Configured) { // is user still connected? command = usbio_get_byte(); if (command == -1) continue; switch (command) { case CMD_GETVERSION: usbio_set_byte(NANDORWAY_MAJOR_VERSION, 0); usbio_set_byte(NANDORWAY_MINOR_VERSION, 0); usbio_set_byte(NANDORWAY_BUILD_VERSION, 1); break; case CMD_PING: usbio_set_byte(0x42, 0); usbio_set_byte(0xbd, 1); break; case CMD_BOOTLOADER: bootloader(); break; case CMD_SPEEDTEST_READ: speedtest_send(); break; case CMD_SPEEDTEST_WRITE: speedtest_receive(); break; case CMD_IO_LOCK: nor_initports(); break; case CMD_IO_RELEASE: nor_releaseports(); break; case CMD_NOR_ID: nor_id(); break; case CMD_NOR_RESET: nor_reset(); break; case CMD_NOR_ERASE_SECTOR: nor_erase_sector(); break; case CMD_NOR_ERASE_CHIP: nor_erase_chip(); break; case CMD_NOR_ADDRESS_SET: nor_address_set(usbio_get_byte(), usbio_get_byte(), usbio_get_byte()); break; case CMD_NOR_ADDRESS_INCREMENT: nor_address_increment(1); break; case CMD_NOR_ADDRESS_INCREMENT_ENABLE: nor_address_increment_set(1); break; case CMD_NOR_ADDRESS_INCREMENT_DISABLE: nor_address_increment_set(0); break; case CMD_NOR_2ND_DIE_ENABLE: nor_2nd_die_offset(0x40); //A22=HIGH for Samsung K8Q2815 break; case CMD_NOR_2ND_DIE_DISABLE: nor_2nd_die_offset(0x00); //A22=LOW for Samsung K8Q2815 break; case CMD_NOR_READ_WORD: nor_read(NOR_BSS_WORD, 1); break; case CMD_NOR_READ_BLOCK_4KB: nor_read(NOR_BSS_4, 1); break; case CMD_NOR_READ_BLOCK_8KB: nor_read(NOR_BSS_8, 1); break; case CMD_NOR_READ_BLOCK_64KB: nor_read(NOR_BSS_64, 1); break; case CMD_NOR_READ_BLOCK_128KB: nor_read(NOR_BSS_128, 1); break; case CMD_NOR_WRITE_WORD: nor_write_word(); break; case CMD_NOR_WRITE_BLOCK_WORD: nor_write_block(NOR_PRG_MODE_WORD); break; case CMD_NOR_WRITE_BLOCK_UBM: nor_write_block(NOR_PRG_MODE_UBM); break; case CMD_NOR_WRITE_BLOCK_WBP: nor_write_block(NOR_PRG_MODE_WBP); break; case CMD_NAND_ID: switch (nand_id) { case 0: if (init_nand(&nand0) == 1) { //24 bytes usbio_set_byte(nand0.info.maker_code, 0); usbio_set_byte(nand0.info.device_code, 0); usbio_set_byte((nand0.info.page_size >> 24) & 0xFF, 0); usbio_set_byte((nand0.info.page_size >> 16) & 0xFF, 0); usbio_set_byte((nand0.info.page_size >> 8) & 0xFF, 0); usbio_set_byte(nand0.info.page_size & 0xFF, 0); usbio_set_byte(nand0.info.oob->size, 0); usbio_set_byte((nand0.info.block_size >> 24) & 0xFF, 0); usbio_set_byte((nand0.info.block_size >> 16) & 0xFF, 0); usbio_set_byte((nand0.info.block_size >> 8) & 0xFF, 0); usbio_set_byte(nand0.info.block_size & 0xFF, 0); usbio_set_byte((nand0.info.num_blocks >> 24) & 0xFF, 0); usbio_set_byte((nand0.info.num_blocks >> 16) & 0xFF, 0); usbio_set_byte((nand0.info.num_blocks >> 8) & 0xFF, 0); usbio_set_byte(nand0.info.num_blocks & 0xFF, 0); usbio_set_byte(nand0.info.num_planes, 0); usbio_set_byte((nand0.info.plane_size >> 56) & 0xFF, 0); usbio_set_byte((nand0.info.plane_size >> 48) & 0xFF, 0); usbio_set_byte((nand0.info.plane_size >> 40) & 0xFF, 0); usbio_set_byte((nand0.info.plane_size >> 32) & 0xFF, 0); usbio_set_byte((nand0.info.plane_size >> 24) & 0xFF, 0); usbio_set_byte((nand0.info.plane_size >> 16) & 0xFF, 0); usbio_set_byte((nand0.info.plane_size >> 8) & 0xFF, 0); usbio_set_byte(nand0.info.plane_size & 0xFF, 1); } else { for (uint8_t i = 0; i < 23; ++i) usbio_set_byte(0xFF, 0); usbio_set_byte(0xFF, 1); } break; case 1: if (init_nand(&nand1) == 1) { //24 bytes usbio_set_byte(nand1.info.maker_code, 0); usbio_set_byte(nand1.info.device_code, 0); usbio_set_byte((nand1.info.page_size >> 24) & 0xFF, 0); usbio_set_byte((nand1.info.page_size >> 16) & 0xFF, 0); usbio_set_byte((nand1.info.page_size >> 8) & 0xFF, 0); usbio_set_byte(nand1.info.page_size & 0xFF, 0); usbio_set_byte(nand1.info.oob->size, 0); usbio_set_byte((nand1.info.block_size >> 24) & 0xFF, 0); usbio_set_byte((nand1.info.block_size >> 16) & 0xFF, 0); usbio_set_byte((nand1.info.block_size >> 8) & 0xFF, 0); usbio_set_byte(nand1.info.block_size & 0xFF, 0); usbio_set_byte((nand1.info.num_blocks >> 24) & 0xFF, 0); usbio_set_byte((nand1.info.num_blocks >> 16) & 0xFF, 0); usbio_set_byte((nand1.info.num_blocks >> 8) & 0xFF, 0); usbio_set_byte(nand1.info.num_blocks & 0xFF, 0); usbio_set_byte(nand1.info.num_planes, 0); usbio_set_byte((nand1.info.plane_size >> 56) & 0xFF, 0); usbio_set_byte((nand1.info.plane_size >> 48) & 0xFF, 0); usbio_set_byte((nand1.info.plane_size >> 40) & 0xFF, 0); usbio_set_byte((nand1.info.plane_size >> 32) & 0xFF, 0); usbio_set_byte((nand1.info.plane_size >> 24) & 0xFF, 0); usbio_set_byte((nand1.info.plane_size >> 16) & 0xFF, 0); usbio_set_byte((nand1.info.plane_size >> 8) & 0xFF, 0); usbio_set_byte(nand1.info.plane_size & 0xFF, 1); } else { for (uint8_t i = 0; i < 23; ++i) usbio_set_byte(0xFF, 0); usbio_set_byte(0xFF, 1); } break; default: break; }