/* * Init TWI interface for WM8731 . */ static void init_twi_wm8731(void) { twi_options_t opt; /* Configure the options of TWI driver */ opt.master_clk = sysclk_get_peripheral_hz(); opt.speed = TWI_WM8731_CLK; opt.chip = WM8731_SLAVE_ADDRESS; twi_master_setup(TWI_WM8731, &opt); }
void configure_twi( void ) { twi_master_options_t * p_opt = (twi_master_options_t * ) pvPortMalloc (sizeof(twi_master_options_t)); p_opt->speed = TWI0_SPEED; p_opt->chip = TWI0_CHIP; twi_master_setup(TWI0, p_opt); // twi_enable_interrupt(TWI0, TWI0_INTERRUPT_FLAGS); }
/** * \brief Initialize TWI communication interface. */ static void init_interface(void) { /** TWI master initialization options. */ twi_master_options_t twi_opt; memset((void *)&twi_opt, 0, sizeof(twi_master_options_t)); /** 100KHz for I2C speed */ twi_opt.speed = 100000; /** Initialize the TWI master driver. */ twi_master_setup(BOARD_QT_TWI_INSTANCE, &twi_opt); }
/* Init the CDCE906 chip, set offline */ bool cdce906_init(void) { gpio_configure_pin(PIN_CDCE_SDA, PIN_CDCE_SDA_FLAGS); gpio_configure_pin(PIN_CDCE_SCL, PIN_CDCE_SCL_FLAGS); twi_master_options_t opt = { .speed = 50000, .chip = CDCE906_ADDR }; twi_master_setup(TWI1, &opt); uint8_t data = 0; /* Read addr 0 */ if (cdce906_read(0, &data) == false){ return false; } /* Check vendor ID matches expected */ if ((data & 0x0F) == 0x01){ return true; } return false; } bool cdce906_write(uint8_t addr, uint8_t data) { twi_package_t packet_write = { .addr = {0x80 | addr}, // TWI slave memory address data .addr_length = 1, // TWI slave memory address data size .chip = CDCE906_ADDR, // TWI slave bus address .buffer = &data, // transfer data source buffer .length = 1 // transfer data size (bytes) }; if (twi_master_write(TWI1, &packet_write) == TWI_SUCCESS){ return true; } else { return false; } }
/*! \brief Initializes the two-wire interface */ static void init_twi(uint32_t fpba_hz) { volatile uint32_t i; static const gpio_map_t CS2200_TWI_GPIO_MAP = { {AVR32_TWI_SCL_0_0_PIN, AVR32_TWI_SCL_0_0_FUNCTION}, {AVR32_TWI_SDA_0_0_PIN, AVR32_TWI_SDA_0_0_FUNCTION} }; static twi_master_options_t CS2200_TWI_OPTIONS = { .speed = CS2200_TWI_MASTER_SPEED, .chip = CS2200_TWI_SLAVE_ADDRESS }; CS2200_TWI_OPTIONS.pba_hz = fpba_hz; gpio_enable_module(CS2200_TWI_GPIO_MAP, sizeof(CS2200_TWI_GPIO_MAP) / sizeof(CS2200_TWI_GPIO_MAP[0])); twi_master_setup(CS2200_TWI, &CS2200_TWI_OPTIONS); }
/** * \brief Set maXTouch configuration * * This function writes a set of predefined, optimal maXTouch configuration data * to the mXT143E Xplained. * * \param device Pointer to mxt_device struct */ static void mxt_init(struct mxt_device *device) { enum status_code status; UNUSED(status); /* T8 configuration object data */ uint8_t t8_object[] = { 0x10, 0x05, 0x0a, 0x14, 0x64, 0x00, 0x05, 0x0a, 0x00, 0x00, }; /* T9 configuration object data */ uint8_t t9_object[] = { 0x8f, 0x00, 0x00, 0x0d, 0x0b, 0x00, 0x21, 0x3c, 0x0f, 0x00, 0x32, 0x01, 0x01, 0x00, 0x08, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x37, 0x37, 0x8f, 0x50, 0xcf, 0x6e, 0x00, 0x02, 0x2f, 0x2c, 0x00 }; /* T48 configuration object data */ uint8_t t48_object[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* TWI configuration */ twi_master_options_t twi_opt = { .speed = MXT_TWI_SPEED, .chip = MAXTOUCH_TWI_ADDRESS, }; status = twi_master_setup(TWI_INTERFACE, &twi_opt); Assert(status == STATUS_OK); /* Initialize the maXTouch device */ status = mxt_init_device(device, TWI_INTERFACE, MAXTOUCH_TWI_ADDRESS, MXT143E_XPLAINED_CHG); Assert(status == STATUS_OK); /* Issue soft reset of maXTouch device by writing a non-zero value to * the reset register */ mxt_write_config_reg(device, mxt_get_object_address(device, MXT_GEN_COMMANDPROCESSOR_T6, 0) + MXT_GEN_COMMANDPROCESSOR_RESET, 0x01); /* Wait for the reset of the device to complete */ delay_ms(MXT_RESET_TIME); /* Write data to configuration registers in T7 configuration object */ mxt_write_config_reg(device, mxt_get_object_address(device, MXT_GEN_POWERCONFIG_T7, 0) + 0, 0xff); mxt_write_config_reg(device, mxt_get_object_address(device, MXT_GEN_POWERCONFIG_T7, 0) + 1, 0xff); mxt_write_config_reg(device, mxt_get_object_address(device, MXT_GEN_POWERCONFIG_T7, 0) + 2, 0x32); /* Write predefined configuration data to configuration objects */ mxt_write_config_object(device, mxt_get_object_address(device, MXT_GEN_ACQUISITIONCONFIG_T8, 0), &t8_object); mxt_write_config_object(device, mxt_get_object_address(device, MXT_TOUCH_MULTITOUCHSCREEN_T9, 0), &t9_object); mxt_write_config_object(device, mxt_get_object_address(device, MXT_PROCG_TOUCHSUPPRESSION_T48, 0), &t48_object); /* Issue recalibration command to maXTouch device by writing a non-zero * value to the calibrate register */ mxt_write_config_reg(device, mxt_get_object_address(device, MXT_GEN_COMMANDPROCESSOR_T6, 0) + MXT_GEN_COMMANDPROCESSOR_CALIBRATE, 0x01); }
int main(void) { static uint8_t ret = 0; uint8_t i = 0; uint8_t ibuf[16] = {0}; static uint8_t test_pattern[PATTERN_TEST_LENGTH]; sensor_data_t sensor_data; twi_master_options_t opt; irq_initialize_vectors(); sysclk_init(); /* Initialize the board. * The board-specific conf_board.h file contains the configuration of * the board initialization. */ board_init(); gfx_mono_init(); ioport_set_pin_high(NHD_C12832A1Z_BACKLIGHT); gfx_mono_draw_string("Reading....\r\n", 0, 0, &sysfont); gfx_mono_generic_draw_filled_rect(0, 8, 128, 8, GFX_PIXEL_CLR); /* configure the pins connected to LEDs as output and set their default * initial state to low (LEDs off). */ ioport_configure_pin(LED_LOW, IOPORT_DIR_OUTPUT); ioport_configure_pin(LED_HIGH, IOPORT_DIR_OUTPUT); ioport_configure_pin(LED_CRIT, IOPORT_DIR_OUTPUT); ioport_configure_pin(LED_NORM, IOPORT_DIR_OUTPUT); ioport_set_pin_low(LED_LOW); ioport_set_pin_low(LED_HIGH); ioport_set_pin_low(LED_CRIT); ioport_set_pin_low(LED_NORM); /* Configure the ALERT/EVENT pin which is * routed to pin 2 of J2 on A3BU Xplained * This pin can be used for polling or interrupt */ ioport_configure_pin(EVENT_PIN, IOPORT_DIR_INPUT); attach_device(EXAMPLE_TS_DEVICE_ADDR, EXAMPLE_TS_DEVICE); opt.chip = EXAMPLE_TS_DEVICE_ADDR; opt.speed = TWI_SPEED; /* Initialize TWI driver with options */ twi_master_setup(TWI_MODULE, &opt); sensor_data.config_reg.value = 0; /* Set configuration register to 12-bis resolution */ sensor_data.config_reg.option.RES = AT30TS7_RES12; if (write_config(sensor_data.config_reg.value) != TWI_SUCCESS) { test_fail_indication(); } /* Set the polarity of ALERT/EVENT pin to low */ if (set_config_option(&sensor_data, AT30TS_POL, AT30TS7_POL_ACTIVE_LOW) != TWI_SUCCESS) { test_fail_indication(); } /* Read the configuration register */ if (read_config(&sensor_data) != TWI_SUCCESS) { test_fail_indication(); } #if defined _AT30TS00_ || defined _AT30TSE002B_ /* Set t_high limit register to +75.0000C */ if (write_tcrit(pos, 75, 0000) != TWI_SUCCESS) { test_fail_indication(); } #endif /* Set t_high limit register to +50.7500C */ if (write_temperature_high(pos, 50, 7500) != TWI_SUCCESS) { test_fail_indication(); } /* Set t_low limit register to -25.2500C */ /* * if (write_temperature_low(neg, 25, 2500)!= TWI_SUCCESS) { * test_fail_indication(); * } */ /* Set t_low limit register to +35.5000C */ if (write_temperature_low(pos, 35, 5000) != TWI_SUCCESS) { test_fail_indication(); } #if defined _AT30TS00_ || defined _AT30TSE002B_ /* Read t_crit register register */ if (read_tcrit(&sensor_data) != TWI_SUCCESS) { test_fail_indication(); } #endif /* Read t_high limit register */ if (read_temperature_high(&sensor_data) != TWI_SUCCESS) { test_fail_indication(); } /* Read t_low register register */ if (read_temperature_low(&sensor_data) != TWI_SUCCESS) { test_fail_indication(); } /* Non volatile register functionality */ #if defined _AT30TS750_ || defined _AT30TSE752_ || \ defined _AT30TSE754_ || defined _AT30TSE758_ /* Copy volatile registers to nonvolatile registers * vol configuration register -> nonvol configuration register * vol t_high register -> nonvol t_high register * vol t_low register -> nonvol t_low register */ ret = ts75_copy_vol_nonvol_register(); if (ret != TWI_SUCCESS) { test_fail_indication(); } /* Read the nonvol configuration register */ if (read_nvconfig(&sensor_data) != TWI_SUCCESS) { test_fail_indication(); } /* Read the nonvol t_high register */ if (read_nvthigh(&sensor_data) != TWI_SUCCESS) { test_fail_indication(); } /* Read the nonvol t_low register */ if (read_nvtlow(&sensor_data) != TWI_SUCCESS) { test_fail_indication(); } /* Clear vol configuration register */ if (write_config(0x0000) != TWI_SUCCESS) { test_fail_indication(); } /* Read the vol configuration register */ if (read_config(&sensor_data) != TWI_SUCCESS) { test_fail_indication(); } /* Copy nonvolatile registers to volatile registers */ if (ts75_copy_nonvol_vol_register() != TWI_SUCCESS) { test_fail_indication(); } /* Read the configuration register */ if (read_config(&sensor_data) != TWI_SUCCESS) { test_fail_indication(); } #endif /* To avoid 'variable unused' warning */ test_pattern[0] = ibuf[0]; ibuf[0] = test_pattern[0]; /* EEPROM Test */ #if defined _AT30TSE002B_ || defined _AT30TSE752_ || \ defined _AT30TSE754_ || defined _AT30TSE758_ /* Generate Test Pattern */ for (i = 0; i < PATTERN_TEST_LENGTH; i++) { test_pattern[i] = 0x41 + i; // 'ABCD...' } /* Perform a write access & check write result */ if ((ret = ts_write_memory(EE_TEST_ADDR, PATTERN_TEST_LENGTH, (void *)test_pattern)) != TWI_SUCCESS) { gfx_mono_draw_string("EE Write Failed ", 0, 24, &sysfont); test_fail_indication(); } /* Allow time for EEPROM to settle */ delay_ms(5); /* Clear test_pattern */ memset(ibuf, 0, sizeof(ibuf)); /* Perform a read access & check read result */ if (ts_read_eeprom(EE_TEST_ADDR, PATTERN_TEST_LENGTH, ibuf) != TWI_SUCCESS) { gfx_mono_draw_string("EE Read Failed ", 0, 24, &sysfont); test_fail_indication(); } /* Check received data against sent data */ for (i = 0; i < PATTERN_TEST_LENGTH; i++) { if (ibuf[i] != test_pattern[i]) { gfx_mono_draw_string("EE Read mismatch ", 0, 24, &sysfont); test_fail_indication(); } } gfx_mono_draw_string("EE Write/Read OK", 0, 24, &sysfont); gfx_mono_draw_string((char const*)ibuf, 0, 16, &sysfont); #endif /* * Temperature reading contained in struct,i.e. * temperature register value = 0x3240 (+50.25C), AT30TSE758 device * sensor_data.temperature.itemp = 50 //!< integer part * sensor_data.temperature.ftemp = 2500 //!< fractional part * sensor_data.temperature.sign = 0 //!< sign (pos(+) = 0, neg(-) = 1) * sensor_data.temperature.raw_value = 0x324 //!< raw data */ char senseData[50] = {0}; while (1) { /* Read temperature */ read_temperature(&sensor_data); sprintf(senseData, "%d.%04d DegC", sensor_data.temperature.itemp, sensor_data.temperature.ftemp); gfx_mono_draw_string(senseData, 0, 8, &sysfont); ioport_set_pin_low(LED_NORM); delay_ms(200); ioport_set_pin_high(LED_NORM); delay_ms(200); } }
/** * Periodic task */ static void masterHandler(void) { static twiRequestT req; static enum { idleTS = 0, queryRegulatorTemperature1TS, waitForRegulatorTemperature1TS, queryRegulatorTemperature2TS, waitForRegulatorTemperature2TS, queryRegulatorFailCodesTS, waitForRegulatorFailCodesTS, queryRegulatorCurrentFaultTS, waitForRegulatorCurrentFaultTS, queryRegulatorPhaseFaultTS, waitForRegulatorPhaseFaultTS, queryInputVoltageTS, waitForInputVoltageTS, queryOutputVoltageTS, waitForOutputVoltageTS, queryBoardTempsTS, waitForBoardTempsTS, queryTachsTS, waitForTachsTS, queryPowerStatusTS, waitForPowerStatusTS } state; static enum { resetBS = 0, idleBS, retrySubmitBS, busyBS } busState[TWI_BUS_COUNT]; static uint16_t lastModulePoll; static uint16_t lastIRPoll; static uint16_t watchdog[TWI_BUS_COUNT]; static uint8_t txBuffer[16]; static uint8_t rxBuffer[32]; static uint8_t slave; static uint8_t ir; static int16_t temperature; int status; uint16_t v; uint8_t i; spiFpgaTwiMasterHandler(); for (i = 0; i < TWI_BUS_COUNT; i++) { if (masterRequestHead[i]) { switch (busState[i]) { case resetBS: switch (i) { case TWI_BUS_UC: twiReset(); twi_master_setup(); break; case TWI_BUS_FPGA: spiFpgaTwiReset(); break; } busState[i] = idleBS; break; case idleBS: /* fall through */ case retrySubmitBS: switch (i) { case TWI_BUS_UC: status = twiMasterWriteRead(masterRequestHead[TWI_BUS_UC]->addr, masterRequestHead[TWI_BUS_UC]->tx, masterRequestHead[TWI_BUS_UC]->txLength, masterRequestHead[TWI_BUS_UC]->rx, masterRequestHead[TWI_BUS_UC]->rxLength); break; case TWI_BUS_FPGA: status = spiFpgaTwiMasterWriteRead(masterRequestHead[TWI_BUS_FPGA]->addr, masterRequestHead[TWI_BUS_FPGA]->tx, masterRequestHead[TWI_BUS_FPGA]->txLength, masterRequestHead[TWI_BUS_FPGA]->rx, masterRequestHead[TWI_BUS_FPGA]->rxLength); break; } if (status == TWI_SUCCESS) { busState[i] = busyBS; watchdog[i] = msec_ticker; } else { if (busState[i] == idleBS) { watchdog[i] = msec_ticker; busState[i] = retrySubmitBS; } else if (elapsed_since(watchdog[i]) > TWI_TIME_MAX) { masterRequestHead[i]->result = status; masterRequestHead[i]->pending = 0; masterRequestHead[i] = masterRequestHead[i]->next; busState[i] = resetBS; } } break; case busyBS: switch (i) { case TWI_BUS_UC: status = twiStatus(); break; case TWI_BUS_FPGA: status = spiFpgaTwiStatus(); break; } if (status != TWI_BUSY) { masterRequestHead[i]->result = status; masterRequestHead[i]->pending = 0; masterRequestHead[i] = masterRequestHead[i]->next; busState[i] = idleBS; } else if (elapsed_since(watchdog[i]) > TWI_TIME_MAX) { masterRequestHead[i]->result = TWI_TIMEOUT; masterRequestHead[i]->pending = 0; masterRequestHead[i] = masterRequestHead[i]->next; busState[i] = resetBS; } break; } } } switch (state) { case idleTS: if (boardid == iraBID && elapsed_since(lastIRPoll) >= TWI_IR_POLLING_INTERVAL) { lastIRPoll = msec_ticker; ir = 0; state = queryRegulatorTemperature1TS; } else if (ucinfo.master && ucinfo.num_slaves && elapsed_since(lastModulePoll) >= TWI_MODULE_POLLING_INTERVAL) { lastModulePoll = msec_ticker; slave = 0; state = queryBoardTempsTS; } break; /* * Regulator Temperature 1 */ case queryRegulatorTemperature1TS: txBuffer[0] = IR3566B_REG_TEMP1; req.addr = TWI_IR3566B_STARTADDR + ir; req.tx = txBuffer; req.txLength = 1; req.rx = rxBuffer; req.rxLength = 1; twiQueueRequest(TWI_BUS_IR3566B, &req); state = waitForRegulatorTemperature1TS; break; case waitForRegulatorTemperature1TS: if (!req.pending) { if (req.result == TWI_SUCCESS) temperature = rxBuffer[0]; else temperature = -1; state = queryRegulatorTemperature2TS; } break; /* * Regulator Temperature 2 */ case queryRegulatorTemperature2TS: txBuffer[0] = IR3566B_REG_TEMP2; req.addr = TWI_IR3566B_STARTADDR + ir; req.tx = txBuffer; req.txLength = 1; req.rx = rxBuffer; req.rxLength = 1; twiQueueRequest(TWI_BUS_IR3566B, &req); state = waitForRegulatorTemperature2TS; break; case waitForRegulatorTemperature2TS: if (!req.pending) { if (req.result == TWI_SUCCESS) { if ((int16_t) rxBuffer[0] > temperature) temperature = rxBuffer[0]; } if (temperature >= 0) gwq_update_board_temperature(ir, 0x1000 | (uint16_t) temperature); state = queryRegulatorFailCodesTS; } break; /* * Regulator Fail Codes */ case queryRegulatorFailCodesTS: txBuffer[0] = IR3566B_REG_L1_FAIL; req.addr = TWI_IR3566B_STARTADDR + ir; req.tx = txBuffer; req.txLength = 1; req.rx = rxBuffer; req.rxLength = 1; twiQueueRequest(TWI_BUS_IR3566B, &req); state = waitForRegulatorFailCodesTS; break; case waitForRegulatorFailCodesTS: if (!req.pending) { if (req.result == TWI_SUCCESS) { if (rxBuffer[0]) { /* a failure code is pending */ if (rxBuffer[0] & IR3566B_REG_L1_FAIL_OVER_TEMP) usbctrlDebugStreamPrintf("Regulator %d Fail: Over Temp\n", ir); if (rxBuffer[0] & IR3566B_REG_L1_FAIL_OVER_CURRENT) usbctrlDebugStreamPrintf("Regulator %d Fail: Over Current\n", ir); if (rxBuffer[0] & IR3566B_REG_L1_FAIL_VCPU_HIGH) usbctrlDebugStreamPrintf("Regulator %d Fail: VCPU High\n", ir); if (rxBuffer[0] & IR3566B_REG_L1_FAIL_VCPU_LOW) usbctrlDebugStreamPrintf("Regulator %d Fail: VCPU Low\n", ir); if (rxBuffer[0] & IR3566B_REG_L1_FAIL_V12_LOW) usbctrlDebugStreamPrintf("Regulator %d Fail: V12 Low\n", ir); if (rxBuffer[0] & IR3566B_REG_L1_FAIL_V3_LOW) usbctrlDebugStreamPrintf("Regulator %d Fail: V3 Low\n", ir); if (rxBuffer[0] & IR3566B_REG_L1_FAIL_PHASE_FAULT) usbctrlDebugStreamPrintf("Regulator %d Fail: Phase Fault\n", ir); if (rxBuffer[0] & IR3566B_REG_L1_FAIL_SLOW_OVER_CURRENT) usbctrlDebugStreamPrintf("Regulator %d Fail: Slow Over Current\n", ir); /* clear sticky codes */ txBuffer[0] = IR3566B_REG_CLEAR_FAIL; txBuffer[1] = IR3566B_REG_CLEAR_FAIL_L1_STICKY; req.addr = TWI_IR3566B_STARTADDR + ir; req.tx = txBuffer; req.txLength = 2; req.rx = rxBuffer; req.rxLength = 0; twiQueueRequest(TWI_BUS_IR3566B, &req); } } state = queryRegulatorCurrentFaultTS; } break; /* * Regulator Current Fault */ case queryRegulatorCurrentFaultTS: txBuffer[0] = IR3566B_REG_L1_CURRENT_FAULT; req.addr = TWI_IR3566B_STARTADDR + ir; req.tx = txBuffer; req.txLength = 1; req.rx = rxBuffer; req.rxLength = 1; twiQueueRequest(TWI_BUS_IR3566B, &req); state = waitForRegulatorCurrentFaultTS; break; case waitForRegulatorCurrentFaultTS: if (!req.pending) { if (req.result == TWI_SUCCESS) { if ((rxBuffer[0] & IR3566B_REG_L1_CURRENT_FAULT_MAX) || (rxBuffer[0] & IR3566B_REG_L1_CURRENT_FAULT_MIN)) { /* a failure code is pending */ if (rxBuffer[0] & IR3566B_REG_L1_CURRENT_FAULT_MIN) usbctrlDebugStreamPrintf("Regulator %d Current Fault: Min\n", ir); if (rxBuffer[0] & IR3566B_REG_L1_CURRENT_FAULT_MAX) usbctrlDebugStreamPrintf("Regulator %d Current Fault: Max\n", ir); /* read the phase that is generating the fault */ state = queryRegulatorPhaseFaultTS; } else { /* move to next statistic */ state = queryInputVoltageTS; } } } break; /* * Regulator Phase Fault */ case queryRegulatorPhaseFaultTS: txBuffer[0] = IR3566B_REG_PHASE_FAULT; req.addr = TWI_IR3566B_STARTADDR + ir; req.tx = txBuffer; req.txLength = 1; req.rx = rxBuffer; req.rxLength = 1; twiQueueRequest(TWI_BUS_IR3566B, &req); state = waitForRegulatorPhaseFaultTS; break; case waitForRegulatorPhaseFaultTS: if (!req.pending) { if (req.result == TWI_SUCCESS) { /* report which phase is generating the fault */ if (rxBuffer[0] == IR3566B_REG_PHASE_FAULT_PHASE1) usbctrlDebugStreamWriteStr("Fault in Phase 1\n"); if (rxBuffer[0] == IR3566B_REG_PHASE_FAULT_PHASE2) usbctrlDebugStreamWriteStr("Fault in Phase 2\n"); if (rxBuffer[0] == IR3566B_REG_PHASE_FAULT_PHASE3) usbctrlDebugStreamWriteStr("Fault in Phase 3\n"); if (rxBuffer[0] == IR3566B_REG_PHASE_FAULT_PHASE4) usbctrlDebugStreamWriteStr("Fault in Phase 4\n"); if (rxBuffer[0] == IR3566B_REG_PHASE_FAULT_PHASE5) usbctrlDebugStreamWriteStr("Fault in Phase 5\n"); if (rxBuffer[0] == IR3566B_REG_PHASE_FAULT_PHASE6) usbctrlDebugStreamWriteStr("Fault in Phase 6\n"); if (rxBuffer[0] == IR3566B_REG_PHASE_FAULT_PHASE7) usbctrlDebugStreamWriteStr("Fault in Phase 7\n"); /* clear the phase fault */ txBuffer[0] = IR3566B_REG_CLEAR_PHASE_FAULT; txBuffer[1] = IR3566B_REG_CLEAR_PHASE_FAULT_BIT; req.addr = TWI_IR3566B_STARTADDR + ir; req.tx = txBuffer; req.txLength = 2; req.rx = rxBuffer; req.rxLength = 0; twiQueueRequest(TWI_BUS_IR3566B, &req); } state = queryInputVoltageTS; } break; /* * Regulator Input Voltage */ case queryInputVoltageTS: txBuffer[0] = IR3566B_REG_VIN_SUPPLY; req.addr = TWI_IR3566B_STARTADDR + ir; req.tx = txBuffer; req.txLength = 1; req.rx = rxBuffer; req.rxLength = 1; twiQueueRequest(TWI_BUS_IR3566B, &req); state = waitForInputVoltageTS; break; case waitForInputVoltageTS: if (!req.pending) { if (req.result == TWI_SUCCESS) moduleStatus[0].inputMillivolts[ir] = (uint16_t) ((uint32_t) rxBuffer[0] * 1000 / 8); state = queryOutputVoltageTS; } break; /* * Regulator Output Voltage */ case queryOutputVoltageTS: txBuffer[0] = IR3566B_REG_L1_VOUT; req.addr = TWI_IR3566B_STARTADDR + ir; req.tx = txBuffer; req.txLength = 1; req.rx = rxBuffer; req.rxLength = 1; twiQueueRequest(TWI_BUS_IR3566B, &req); state = waitForOutputVoltageTS; break; case waitForOutputVoltageTS: if (!req.pending) { if (req.result == TWI_SUCCESS) { moduleStatus[0].outputMillivolts[ir] = (uint16_t) ((uint32_t) rxBuffer[0] * 1000 / 128); } if (++ir < 4) { state = queryRegulatorTemperature1TS; } else { state = idleTS; } } break; /* * Board Temperatures */ case queryBoardTempsTS: txBuffer[0] = TWICMD_BOARD_TEMPERATURES; req.addr = TWI_SLAVE_STARTADDR + slave; req.tx = txBuffer; req.txLength = 1; req.rx = rxBuffer; req.rxLength = 8; twiQueueRequest(TWI_BUS_UC, &req); state = waitForBoardTempsTS; break; case waitForBoardTempsTS: if (!req.pending) { if (req.result == TWI_SUCCESS) { for (i = 0; i < 4; i++) { v = ((uint16_t) rxBuffer[i * 2 + 0] << 8) | rxBuffer[i * 2 + 1]; gwq_update_board_temperature((slave + 1) * 4 + i, v); } } state = queryTachsTS; } break; /* * Board Tachs */ case queryTachsTS: txBuffer[0] = TWICMD_TACHS; req.addr = TWI_SLAVE_STARTADDR + slave; req.tx = txBuffer; req.txLength = 1; req.rx = rxBuffer; req.rxLength = 8; twiQueueRequest(TWI_BUS_UC, &req); state = waitForTachsTS; break; case waitForTachsTS: if (!req.pending) { if (req.result == TWI_SUCCESS) { for (i = 0; i < 4; i++) { v = ((uint16_t) rxBuffer[i * 2 + 0] << 8) | rxBuffer[i * 2 + 1]; gwq_update_tach((slave + 1) * 4 + i, v); } } state = queryPowerStatusTS; } break; /* * Board Power Status */ case queryPowerStatusTS: txBuffer[0] = TWICMD_POWER_STATUS; req.addr = TWI_SLAVE_STARTADDR + slave; req.tx = txBuffer; req.txLength = 1; req.rx = rxBuffer; req.rxLength = 18; twiQueueRequest(TWI_BUS_UC, &req); state = waitForPowerStatusTS; break; case waitForPowerStatusTS: if (!req.pending) { if (req.result == TWI_SUCCESS) { for (i = 0; i < 4; i++) { v = ((uint16_t) rxBuffer[i * 4 + 2] << 8) | rxBuffer[i * 4 + 3]; moduleStatus[slave + 1].inputMillivolts[i] = v; v = ((uint16_t) rxBuffer[i * 4 + 4] << 8) | rxBuffer[i * 4 + 5]; moduleStatus[slave + 1].outputMillivolts[i] = v; } } if (++slave < ucinfo.num_slaves) state = queryBoardTempsTS; else state = idleTS; } break; } }
ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found ) { ATCAIfaceCfg *head = cfg; uint8_t slaveAddress = 0x01; ATCADevice device; ATCAIface discoverIface; ATCACommand command; ATCAPacket packet; uint32_t execution_time; ATCA_STATUS status; uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; uint8_t revs204[2][4] = { { 0x00, 0x02, 0x00, 0x08 }, { 0x00, 0x04, 0x05, 0x00 } }; int i; /** \brief default configuration, to be reused during discovery process */ ATCAIfaceCfg discoverCfg = { .iface_type = ATCA_I2C_IFACE, .devtype = ATECC508A, .atcai2c.slave_address = 0x07, .atcai2c.bus = busNum, .atcai2c.baud = 400000, //.atcai2c.baud = 100000, .wake_delay = 800, .rx_retries = 3 }; // build an info command packet.param1 = INFO_MODE_REVISION; packet.param2 = 0; device = newATCADevice( &discoverCfg ); discoverIface = atGetIFace( device ); command = atGetCommands( device ); // iterate through all addresses on given i2c bus // all valid 7-bit addresses go from 0x07 to 0x78 for ( slaveAddress = 0x07; slaveAddress <= 0x78; slaveAddress++ ) { discoverCfg.atcai2c.slave_address = slaveAddress << 1; // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent // wake up device // If it wakes, send it a dev rev command. Based on that response, determine the device type // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) if ( hal_i2c_wake( discoverIface ) == ATCA_SUCCESS ) { (*found)++; memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); memset( packet.info, 0x00, sizeof(packet.info)); // get devrev info and set device type accordingly atInfo( command, &packet ); execution_time = atGetExecTime(command, CMD_INFO) + 1; // send the command if ( (status = atsend( discoverIface, (uint8_t*)&packet, packet.txsize )) != ATCA_SUCCESS ) { printf("packet send error\r\n"); continue; } // delay the appropriate amount of time for command to execute atca_delay_ms(execution_time); // receive the response if ( (status = atreceive( discoverIface, &(packet.info[0]), &(packet.rxsize) )) != ATCA_SUCCESS ) continue; if ( (status = isATCAError(packet.info)) != ATCA_SUCCESS ) { printf("command response error\r\n"); continue; } // determine device type from common info and dev rev response byte strings for ( i = 0; i < sizeof(revs508) / 4; i++ ) { if ( memcmp( &packet.info[1], &revs508[i], 4) == 0 ) { discoverCfg.devtype = ATECC508A; break; } } for ( i = 0; i < sizeof(revs204) / 4; i++ ) { if ( memcmp( &packet.info[1], &revs204[i], 4) == 0 ) { discoverCfg.devtype = ATSHA204A; break; } } for ( i = 0; i < sizeof(revs108) / 4; i++ ) { if ( memcmp( &packet.info[1], &revs108[i], 4) == 0 ) { discoverCfg.devtype = ATECC108A; break; } } atca_delay_ms(15); // now the device type is known, so update the caller's cfg array element with it head->devtype = discoverCfg.devtype; head++; } hal_i2c_idle(discoverIface); } deleteATCADevice(&device); return ATCA_SUCCESS; } /** \brief - this HAL implementation assumes you've included the ASF I2C libraries in your project, otherwise, the HAL layer will not compile because the ASF I2C drivers are a dependency * */ /** \brief hal_i2c_init manages requests to initialize a physical interface. it manages use counts so when an interface * has released the physical layer, it will disable the interface for some other use. * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. */ /** \brief initialize an I2C interface using given config * \param[in] hal - opaque ptr to HAL data * \param[in] cfg - interface configuration */ ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) { int bus = cfg->atcai2c.bus; // 0-based logical bus number ATCAHAL_t *phal = (ATCAHAL_t*)hal; if ( i2c_bus_ref_ct == 0 ) // power up state, no i2c buses will have been used for ( int i = 0; i < MAX_I2C_BUSES; i++ ) i2c_hal_data[i] = NULL; i2c_bus_ref_ct++; // total across buses if ( bus >= 0 && bus < MAX_I2C_BUSES ) { // if this is the first time this bus and interface has been created, do the physical work of enabling it if ( i2c_hal_data[bus] == NULL ) { i2c_hal_data[bus] = malloc( sizeof(ATCAI2CMaster_t) ); i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance config_i2c_master.speed = cfg->atcai2c.baud; config_i2c_master.chip = 0x50; config_i2c_master.speed_reg = TWI_BAUD(sysclk_get_cpu_hz(), cfg->atcai2c.baud); switch (bus) { case 0: i2c_hal_data[bus]->i2c_master_instance = &TWIC; break; //case 1: i2c_hal_data[bus]->i2c_master_instance = &TWID; break; // for XMEGA-A1 case 2: i2c_hal_data[bus]->i2c_master_instance = &TWIE; break; //case 3: i2c_hal_data[bus]->i2c_master_instance = &TWIF; break; // for XMEGA-A1 } twi_master_setup((i2c_hal_data[bus]->i2c_master_instance), &config_i2c_master); // store this for use during the release phase i2c_hal_data[bus]->bus_index = bus; twi_master_enable(i2c_hal_data[bus]->i2c_master_instance); } else{ // otherwise, another interface already initialized the bus, so this interface will share it and any different // cfg parameters will be ignored...first one to initialize this sets the configuration i2c_hal_data[bus]->ref_ct++; } phal->hal_data = i2c_hal_data[bus]; return ATCA_SUCCESS; } return ATCA_COMM_FAIL; }
ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); int bus = cfg->atcai2c.bus; twi_package_t packet = { .addr_length = 0, // TWI slave memory address data size .chip = cfg->atcai2c.slave_address >> 1, // TWI slave bus address .buffer = txdata, // transfer data source buffer .length = txlength, // transfer data size (bytes) }; // for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format // other device types that don't require i/o tokens on the front end of a command need a different hal_i2c_send and wire it up instead of this one // this covers devices such as ATSHA204A and ATECCx08A that require a word address value pre-pended to the packet // txdata[0] is using _reserved byte of the ATCAPacket txdata[0] = 0x03; // insert the Word Address Value, Command token txlength++; // account for word address value byte. packet.length = txlength; if ( twi_master_write(i2c_hal_data[bus]->i2c_master_instance, &packet) != STATUS_OK ) return ATCA_COMM_FAIL; return ATCA_SUCCESS; } /** \brief HAL implementation of I2C receive function for ASF I2C * \param[in] iface instance * \param[in] rxdata pointer to space to receive the data * \param[in] rxlength ptr to expected number of receive bytes to request * \return ATCA_STATUS */ ATCA_STATUS hal_i2c_receive( ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); int bus = cfg->atcai2c.bus; int retries = cfg->rx_retries; int status = !STATUS_OK; twi_package_t packet = { .addr_length = 0, // TWI slave memory address data size .chip = cfg->atcai2c.slave_address >> 1, // TWI slave bus address .buffer = rxdata, // transfer data source buffer .length = *rxlength, // transfer data size (bytes) }; while ( retries-- > 0 && status != STATUS_OK ) status = twi_master_read(i2c_hal_data[bus]->i2c_master_instance, &packet); if ( status != STATUS_OK ) return ATCA_COMM_FAIL; return ATCA_SUCCESS; } /** \brief method to change the bus speec of I2C * \param[in] iface interface on which to change bus speed * \param[in] speed baud rate (typically 100000 or 400000) */ void change_i2c_speed( ATCAIface iface, uint32_t speed ) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); int bus = cfg->atcai2c.bus; config_i2c_master.speed = speed; config_i2c_master.speed_reg = TWI_BAUD(sysclk_get_cpu_hz(), speed); twi_master_disable(i2c_hal_data[bus]->i2c_master_instance); switch (bus) { case 0: i2c_hal_data[bus]->i2c_master_instance = &TWIC; break; case 2: i2c_hal_data[bus]->i2c_master_instance = &TWIE; break; } twi_master_setup((i2c_hal_data[bus]->i2c_master_instance), &config_i2c_master); twi_master_enable(i2c_hal_data[bus]->i2c_master_instance); }
/*! \brief TWI Master Example Main * * The master example begins by initializing required board resources. The * system clock, basic GPIO pin mapping, and interrupt vectors are established. * * A memory location on a TWI slave is written with a fixed test pattern which * is then read back into a separate buffer. As a basic sanity check, the * original write-buffer values are compared with values read from the slave to * a separate buffer. An LED on the development board is illuminated when there * is a match between the written and read data. * * \return Nothing. */ int main(void) { /* Initialize the common clock service, board-specific initialization, and * interrupt vector support prior to using the TWI master interfaces. */ sysclk_init(); board_init(); #if (!SAM && !MEGA) irq_initialize_vectors(); #endif // SAM // TWI master initialization options. twi_master_options_t opt; #if SAM memset((void *)&opt, 0, sizeof(opt)); #endif opt.speed = TWI_SPEED; #if (!SAM4L) opt.chip = EEPROM_BUS_ADDR; #endif // Initialize the TWI master driver. twi_master_setup(TWI_EXAMPLE, &opt); // Initialize the platform LED's. #if defined(sam4cek) LED_Off(LED0); #elif defined(sam4cmpdb) || defined(sam4cmsdb) LED_Off(LED4); #else LED_Off(LED0_GPIO); #endif twi_package_t packet = { /** * The SAM3X_EK, SAM3X Arduino board and SAM4C_EK use two bytes length internal * address EEPROM. */ #if defined(sam3xek) || defined(arduinoduex) || defined(sam4cek) || defined(sam4cmpdb) || defined(sam4cmsdb) .addr[0] = EEPROM_MEM_ADDR >> 8, // TWI slave memory address data MSB .addr[1] = EEPROM_MEM_ADDR, // TWI slave memory address data LSB .addr_length = sizeof (uint16_t), // TWI slave memory address data size #else .addr[0] = EEPROM_MEM_ADDR, // TWI slave memory address data MSB .addr_length = sizeof (uint8_t), // TWI slave memory address data size #endif .chip = EEPROM_BUS_ADDR, // TWI slave bus address .buffer = (void *)test_pattern, // transfer data source buffer .length = PATTERN_TEST_LENGTH // transfer data size (bytes) }; // Perform a multi-byte write access then check the result. while (twi_master_write(TWI_EXAMPLE, &packet) != TWI_SUCCESS); uint8_t data_received[PATTERN_TEST_LENGTH] = {0}; twi_package_t packet_received = { #if defined(sam3xek) || defined(arduinoduex) || defined(sam4cek) || defined(sam4cmpdb) || defined(sam4cmsdb) .addr[0] = EEPROM_MEM_ADDR >> 8, // TWI slave memory address data MSB .addr[1] = EEPROM_MEM_ADDR, // TWI slave memory address data LSB .addr_length = sizeof (uint16_t), // TWI slave memory address data size #else .addr[0] = EEPROM_MEM_ADDR, // TWI slave memory address data MSB .addr_length = sizeof (uint8_t), // TWI slave memory address data size #endif .chip = EEPROM_BUS_ADDR, // TWI slave bus address .buffer = data_received, // transfer data destination buffer .length = PATTERN_TEST_LENGTH // transfer data size (bytes) }; // Perform a multi-byte read access then check the result. while (twi_master_read(TWI_EXAMPLE, &packet_received) != TWI_SUCCESS); // Verify that the received data matches the sent data. for (uint32_t i = 0 ; i < PATTERN_TEST_LENGTH; ++i) { if (data_received[i] != test_pattern[i]) { // Error while(1); } } //test PASS #if SAM4C LED_On(LED0); #elif defined(sam4cmpdb) || defined(sam4cmsdb) LED_On(LED4); #else LED_On(LED0_GPIO); #endif while(1); }
/*! \brief TWI Master Example Main * * The master example begins by initializing required board resources. The * system clock, basic GPIO pin mapping, and interrupt vectors are established. * * A memory location on a TWI slave is written with a fixed test pattern which * is then read back into a separate buffer. As a basic sanity check, the * original write-buffer values are compared with values read from the slave to * a separate buffer. An LED on the development board is illuminated when there * is a match between the written and read data. * * \return Nothing. */ int main(void) { /* Initialize the common clock service, board-specific initialization, and * interrupt vector support prior to using the TWI master interfaces. */ sysclk_init(); board_init(); #if !SAM irq_initialize_vectors(); #endif // SAM // TWI master initialization options. twi_master_options_t opt = { .speed = TWI_SPEED, .chip = EEPROM_BUS_ADDR }; // Initialize the TWI master driver. twi_master_setup(TWI_EXAMPLE, &opt); // Initialize the platform LED's. LED_Off(LED0_GPIO); twi_package_t packet = { #if SAM .addr[0] = EEPROM_MEM_ADDR >> 8, // TWI slave memory address data MSB .addr[1] = EEPROM_MEM_ADDR, // TWI slave memory address data LSB .addr_length = sizeof (uint16_t), // TWI slave memory address data size #else .addr[0] = EEPROM_MEM_ADDR, // TWI slave memory address data MSB .addr_length = sizeof (uint8_t), // TWI slave memory address data size #endif .chip = EEPROM_BUS_ADDR, // TWI slave bus address .buffer = (void *)test_pattern, // transfer data source buffer .length = PATTERN_TEST_LENGTH // transfer data size (bytes) }; // Perform a multi-byte write access then check the result. while (twi_master_write(TWI_EXAMPLE, &packet) != TWI_SUCCESS); uint8_t data_received[PATTERN_TEST_LENGTH] = {0}; twi_package_t packet_received = { #if SAM .addr[0] = EEPROM_MEM_ADDR >> 8, // TWI slave memory address data MSB .addr[1] = EEPROM_MEM_ADDR, // TWI slave memory address data LSB .addr_length = sizeof (uint16_t), // TWI slave memory address data size #else .addr[0] = EEPROM_MEM_ADDR, // TWI slave memory address data MSB .addr_length = sizeof (uint8_t), // TWI slave memory address data size #endif .chip = EEPROM_BUS_ADDR, // TWI slave bus address .buffer = data_received, // transfer data destination buffer .length = PATTERN_TEST_LENGTH // transfer data size (bytes) }; // Perform a multi-byte read access then check the result. while (twi_master_read(TWI_EXAMPLE, &packet_received) != TWI_SUCCESS); // Verify that the received data matches the sent data. for (uint32_t i = 0 ; i < PATTERN_TEST_LENGTH; ++i) { if (data_received[i] != test_pattern[i]) { // Error while(1); } } //test PASS LED_On(LED0_GPIO); while(1); }
/** * \brief Application entry point for AT24CXX Component Example. * * \return Unused (ANSI-C compatibility). */ int main(void) { uint32_t i; twi_options_t opt; /* Initialize the SAM system */ sysclk_init(); /* Initialize the board */ board_init(); /* Turn off LEDs */ ioport_set_pin_level(LED0_GPIO, LED0_INACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_INACTIVE_LEVEL); /* Initialize the console UART */ configure_console(); /* Output example information */ puts(STRING_HEADER); /* Configure the options of TWI driver */ opt.master_clk = sysclk_get_cpu_hz(); opt.speed = AT24C_TWI_CLK; if (twi_master_setup(BOARD_AT24C_TWI_INSTANCE, &opt) != TWI_SUCCESS) { puts("AT24CXX initialization is failed.\r"); ioport_set_pin_level(LED0_GPIO, LED0_ACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_ACTIVE_LEVEL); while (1) { /* Capture error */ } } /* Fill EEPROM with memory pattern */ if (at24cxx_fill_pattern(AT24C_MEM_ADDR, AT24C_MEM_ADDR + TEST_DATA_LENGTH - 1, MEMORY_PATTERN) != AT24C_WRITE_SUCCESS) { puts("AT24CXX pattern fill is failed.\r"); ioport_set_pin_level(LED0_GPIO, LED0_ACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_ACTIVE_LEVEL); while (1) { /* Capture error */ } } if (at24cxx_read_continuous(AT24C_MEM_ADDR, TEST_DATA_LENGTH, test_data_rx) != AT24C_READ_SUCCESS) { puts("AT24CXX read packet is failed.\r"); ioport_set_pin_level(LED0_GPIO, LED0_ACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_ACTIVE_LEVEL); while (1) { /* Capture error */ } } /* Compare the sent and the received */ for (i = 0; i < TEST_DATA_LENGTH; i++) { if (MEMORY_PATTERN != test_data_rx[i]) { /* No match */ puts("Pattern comparison: Unmatched!\r"); ioport_set_pin_level(LED0_GPIO, LED0_ACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_ACTIVE_LEVEL); while (1) { /* Capture error */ } } } puts("Pattern comparison: Matched!\r"); /* Send test pattern to EEPROM */ if (at24cxx_write_continuous(AT24C_MEM_ADDR, TEST_DATA_LENGTH, test_data_tx) != AT24C_WRITE_SUCCESS) { puts("AT24CXX write packet is failed.\r"); ioport_set_pin_level(LED0_GPIO, LED0_ACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_ACTIVE_LEVEL); while (1) { /* Capture error */ } } /* Get memory from EEPROM */ if (at24cxx_read_continuous(AT24C_MEM_ADDR, TEST_DATA_LENGTH, test_data_rx) != AT24C_READ_SUCCESS) { puts("AT24CXX read packet is failed.\r"); ioport_set_pin_level(LED0_GPIO, LED0_ACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_ACTIVE_LEVEL); while (1) { /* Capture error */ } } /* Compare the sent and the received */ for (i = 0; i < TEST_DATA_LENGTH; i++) { if (test_data_tx[i] != test_data_rx[i]) { /* No match */ puts("Data comparison: Unmatched!\r"); ioport_set_pin_level(LED0_GPIO, LED0_ACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_ACTIVE_LEVEL); while (1) { /* Capture error */ } } } /* Match */ puts("Data comparison: Matched!\r"); /* Page Operation */ for (i = 0; i < PAGE_SIZE; i++) { page_read_buf[i] = 0; page_write_buf[i] = i; } if (at24cxx_write_page(PAGE_ADDR, PAGE_SIZE, page_write_buf) != AT24C_WRITE_SUCCESS) { puts("AT24CXX page write is failed.\r"); ioport_set_pin_level(LED0_GPIO, LED0_ACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_ACTIVE_LEVEL); while (1) { /* Capture error */ } } if (at24cxx_read_page(PAGE_ADDR, PAGE_SIZE, page_read_buf) != AT24C_READ_SUCCESS) { puts("AT24CXX page read is failed.\r"); ioport_set_pin_level(LED0_GPIO, LED0_ACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_ACTIVE_LEVEL); while (1) { /* Capture error */ } } for (i = 0; i < PAGE_SIZE; i++) { if (page_read_buf[i] != page_write_buf[i]) { /* No match */ puts("Page comparison: Unmatched!\r"); ioport_set_pin_level(LED0_GPIO, LED0_ACTIVE_LEVEL); ioport_set_pin_level(LED1_GPIO, LED1_ACTIVE_LEVEL); while (1) { /* Capture error */ } } } /* Match */ puts("Page comparison: Matched!\r"); while (1) { } }