Files
templates/c/parallel-nand/tests/test_parallel_nand.c

273 lines
9.9 KiB
C

#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#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,
&parallel_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,
&parallel_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, &reg) == PNAND_GAS_OK);
assert(reg == 0x4E44U);
assert(parallel_nand_gas_read(&gas, 0xE001U, &reg) == 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, &reg) == 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, &reg) == 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;
}