#include #include #include #include "parallel_nand.h" #include "parallel_nand_gas.h" typedef struct { char kind; unsigned int value; } event_t; static event_t events[256]; static unsigned int event_count; static pnand_octet_t input_data[32]; static unsigned int input_count; static unsigned int input_pos; static void record(char kind, unsigned int value) { events[event_count].kind = kind; events[event_count].value = value; event_count++; } static int fake_init(void) { return 0; } static void fake_select(void) { record('S', 0); } static void fake_deselect(void) { record('D', 0); } static void fake_cmd(pnand_octet_t v) { record('C', v); } static void fake_addr(pnand_octet_t v) { record('A', v); } static void fake_write(pnand_octet_t v) { record('W', v); } static pnand_octet_t fake_read(void) { return input_pos < input_count ? input_data[input_pos++] : 0xFFU; } static int fake_ready(void) { return 1; } static void fake_wp(int enabled) { record('P', (unsigned int)enabled); } static void fake_delay(unsigned long us) { (void)us; } static const parallel_nand_port_t fake_port = { fake_init, fake_select, fake_deselect, fake_cmd, fake_addr, fake_write, fake_read, fake_ready, fake_wp, fake_delay, 1 }; static void clear_events(void) { event_count = 0U; } static unsigned int find_event(unsigned int start, char kind, unsigned int value) { unsigned int i; for (i = start; i < event_count; i++) { if (events[i].kind == kind && events[i].value == value) return i; } return event_count; } int main(void) { parallel_nand_t nand; pnand_octet_t id[2]; pnand_octet_t bytes[2]; pnand_octet_t main_data[2] = {0xAAU, 0x55U}; pnand_octet_t oob[2] = {0xFFU, 0xFEU}; parallel_nand_gas_t gas; parallel_nand_geometry_t small_geometry = { 2UL, 2UL, 2UL, 4UL, 2U, 2U, 100UL }; parallel_nand_port_t read_only_port; parallel_nand_t read_only_nand; unsigned int pos; unsigned int reg; assert(parallel_nand_init(&nand, &fake_port, ¶llel_nand_mt29f1g08_geometry) == PNAND_OK); assert(events[0].kind == 'D'); assert(events[1].kind == 'P' && events[1].value == 1U); clear_events(); input_data[0] = 0x2CU; input_data[1] = 0xF1U; input_count = 2U; input_pos = 0U; assert(parallel_nand_read_id(&nand, 0U, id, 2U) == PNAND_OK); assert(id[0] == 0x2CU && id[1] == 0xF1U); assert(events[1].kind == 'C' && events[1].value == 0x90U); assert(events[2].kind == 'A' && events[2].value == 0U); clear_events(); input_data[0] = 0x12U; input_data[1] = 0x34U; input_count = 2U; input_pos = 0U; assert(parallel_nand_read_page_slice(&nand, 0x1234UL, 0x56UL, bytes, 2UL) == PNAND_OK); assert(bytes[0] == 0x12U && bytes[1] == 0x34U); assert(events[1].kind == 'C' && events[1].value == 0x00U); assert(events[2].kind == 'A' && events[2].value == 0x56U); assert(events[3].kind == 'A' && events[3].value == 0x00U); assert(events[4].kind == 'A' && events[4].value == 0x34U); assert(events[5].kind == 'A' && events[5].value == 0x12U); assert(events[6].kind == 'C' && events[6].value == 0x30U); assert(parallel_nand_init(&nand, &fake_port, ¶llel_nand_hy27uf084g2m_geometry) == PNAND_OK); assert(parallel_nand_page_count(&nand) == 262144UL); assert(PNAND_HY27UF084G2M_MANUFACTURER_ID == 0xADU); assert(PNAND_HY27UF084G2M_DEVICE_ID == 0xDCU); clear_events(); input_data[0] = 0xABU; input_count = 1U; input_pos = 0U; assert(parallel_nand_read_page_slice(&nand, 0x23456UL, 0x78UL, bytes, 1UL) == PNAND_OK); assert(bytes[0] == 0xABU); assert(events[2].kind == 'A' && events[2].value == 0x78U); assert(events[3].kind == 'A' && events[3].value == 0x00U); assert(events[4].kind == 'A' && events[4].value == 0x56U); assert(events[5].kind == 'A' && events[5].value == 0x34U); assert(events[6].kind == 'A' && events[6].value == 0x02U); assert(events[7].kind == 'C' && events[7].value == 0x30U); assert(parallel_nand_init(&nand, &fake_port, &small_geometry) == PNAND_OK); clear_events(); input_data[0] = 0xFFU; input_data[1] = 0xFFU; input_data[2] = 0x80U; input_count = 3U; input_pos = 0U; assert(parallel_nand_program_page(&nand, 3UL, main_data, 2UL, oob, 2UL) == PNAND_OK); pos = find_event(0U, 'P', 0U); assert(pos < event_count); pos = find_event(pos + 1U, 'C', 0x80U); assert(pos < event_count); pos = find_event(pos + 1U, 'W', 0xAAU); assert(pos < event_count); pos = find_event(pos + 1U, 'W', 0x55U); assert(pos < event_count); pos = find_event(pos + 1U, 'W', 0xFFU); assert(pos < event_count); pos = find_event(pos + 1U, 'W', 0xFEU); assert(pos < event_count); pos = find_event(pos + 1U, 'C', 0x10U); assert(pos < event_count); pos = find_event(pos + 1U, 'C', 0x70U); assert(pos < event_count); assert(events[event_count - 1U].kind == 'P' && events[event_count - 1U].value == 1U); clear_events(); input_data[0] = 0xFFU; input_data[1] = 0xFFU; input_data[2] = 0x80U; input_count = 3U; input_pos = 0U; assert(parallel_nand_erase_block(&nand, 2UL) == PNAND_OK); pos = find_event(0U, 'P', 0U); pos = find_event(pos + 1U, 'C', 0x60U); assert(pos < event_count); pos = find_event(pos + 1U, 'A', 0x04U); assert(pos < event_count); pos = find_event(pos + 1U, 'C', 0xD0U); assert(pos < event_count); assert(events[event_count - 1U].kind == 'P' && events[event_count - 1U].value == 1U); clear_events(); input_data[0] = 0xFFU; input_data[1] = 0xFFU; input_data[2] = 0x81U; input_count = 3U; input_pos = 0U; assert(parallel_nand_program_page(&nand, 0UL, main_data, 2UL, 0, 0UL) == PNAND_ERROR_PROGRAM_FAILED); assert(events[event_count - 1U].kind == 'P' && events[event_count - 1U].value == 1U); clear_events(); input_data[0] = 0xFFU; input_data[1] = 0xFFU; input_data[2] = 0x00U; input_count = 3U; input_pos = 0U; assert(parallel_nand_program_page(&nand, 0UL, main_data, 2UL, 0, 0UL) == PNAND_ERROR_WRITE_PROTECTED); assert(events[event_count - 1U].kind == 'P' && events[event_count - 1U].value == 1U); clear_events(); input_data[0] = 0x00U; input_count = 1U; input_pos = 0U; assert(parallel_nand_erase_block(&nand, 0UL) == PNAND_ERROR_BAD_BLOCK); assert(find_event(0U, 'P', 0U) == event_count); read_only_port = fake_port; read_only_port.write_supported = 0; assert(parallel_nand_init(&read_only_nand, &read_only_port, &small_geometry) == PNAND_OK); assert(parallel_nand_erase_block(&read_only_nand, 0UL) == PNAND_ERROR_WRITE_PROTECTED); parallel_nand_gas_init(&gas, &nand, PNAND_GAS_DEFAULT_BASE); assert(parallel_nand_gas_read(&gas, 0xE000U, ®) == PNAND_GAS_OK); assert(reg == 0x4E44U); assert(parallel_nand_gas_read(&gas, 0xE001U, ®) == PNAND_GAS_OK); assert(reg == 0x0002U); assert(parallel_nand_gas_write(&gas, 0xE005U, 0x1234U) == PNAND_GAS_OK); assert(parallel_nand_gas_write(&gas, 0xE006U, 0x0001U) == PNAND_GAS_OK); assert(gas.selected_page == 0x00011234UL); gas.main_data[0] = 0x34U; gas.main_data[1] = 0x12U; gas.status |= PNAND_GAS_STATUS_PAGE_VALID; assert(parallel_nand_gas_read(&gas, 0xE100U, ®) == PNAND_GAS_OK); assert(reg == 0x1234U); assert(parallel_nand_gas_write(&gas, 0xE000U, 0U) == PNAND_GAS_READ_ONLY); assert((gas.status & PNAND_GAS_STATUS_WRITE_SUPPORTED) != 0U); assert(parallel_nand_gas_write(&gas, 0xE005U, 0U) == PNAND_GAS_OK); assert(parallel_nand_gas_write(&gas, 0xE006U, 0U) == PNAND_GAS_OK); assert(parallel_nand_gas_write(&gas, 0xE004U, PNAND_GAS_CMD_CLEAR_BUFFER) == PNAND_GAS_OK); assert(parallel_nand_gas_write(&gas, 0xE100U, 0x1234U) == PNAND_GAS_OK); assert(gas.main_data[0] == 0x34U && gas.main_data[1] == 0x12U); assert(parallel_nand_gas_write(&gas, 0xE004U, PNAND_GAS_CMD_PROGRAM_PAGE) == PNAND_GAS_REJECTED); assert(gas.error == PNAND_ERROR_CONFIRMATION); assert(parallel_nand_gas_write(&gas, 0xE010U, PNAND_GAS_CONFIRM_MAGIC) == PNAND_GAS_OK); assert(parallel_nand_gas_read(&gas, 0xE002U, ®) == PNAND_GAS_OK); assert(parallel_nand_gas_write(&gas, 0xE004U, PNAND_GAS_CMD_PROGRAM_PAGE) == PNAND_GAS_REJECTED); assert(gas.error == PNAND_ERROR_CONFIRMATION); input_data[0] = 0xFFU; input_data[1] = 0xFFU; input_data[2] = 0x80U; input_count = 3U; input_pos = 0U; assert(parallel_nand_gas_write(&gas, 0xE010U, PNAND_GAS_CONFIRM_MAGIC) == PNAND_GAS_OK); assert(parallel_nand_gas_write(&gas, 0xE004U, PNAND_GAS_CMD_PROGRAM_PAGE) == PNAND_GAS_OK); assert((gas.status & PNAND_GAS_STATUS_BUFFER_DIRTY) == 0U); assert(parallel_nand_gas_write(&gas, 0xE005U, 2U) == PNAND_GAS_OK); input_data[0] = 0xFFU; input_data[1] = 0xFFU; input_data[2] = 0x80U; input_count = 3U; input_pos = 0U; assert(parallel_nand_gas_write(&gas, 0xE010U, PNAND_GAS_CONFIRM_MAGIC) == PNAND_GAS_OK); assert(parallel_nand_gas_write(&gas, 0xE004U, PNAND_GAS_CMD_ERASE_BLOCK) == PNAND_GAS_OK); assert((gas.status & PNAND_GAS_STATUS_PAGE_VALID) == 0U); puts("parallel_nand: OK"); return 0; }