From 73ac1db354b728f90fb1e757df36581b830a4733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Mon, 7 Aug 2017 23:20:45 +0200 Subject: [PATCH] application: implement DS2432 (the reading part) --- application.c | 362 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 322 insertions(+), 40 deletions(-) diff --git a/application.c b/application.c index c60a6dd..a79a2c1 100644 --- a/application.c +++ b/application.c @@ -12,7 +12,7 @@ * along with this program. If not, see . * */ -/** STM32F1 application example +/** STM32F1 Maxim DS2432 (1k-Bit Protected 1-Wire EEPROM with SHA-1 Engine) implementation * @file application.c * @author King Kévin * @date 2016-2017 @@ -167,6 +167,138 @@ error: return; } +/** static table used for the table_driven implementation + * Generated by pycrc v0.9, https://pycrc.org + * using the configuration: + * Width = 16 + * Poly = 0x8005 + * Xor_In = 0x0000 + * ReflectIn = True + * Xor_Out = 0xffff + * ReflectOut = True + * Algorithm = table-driven + */ +static const uint16_t crc_table[256] = { + 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, + 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, + 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, + 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, + 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, + 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, + 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, + 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, + 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, + 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, + 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, + 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, + 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, + 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, + 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, + 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, + 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, + 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, + 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, + 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, + 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, + 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, + 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, + 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, + 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, + 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, + 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, + 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, + 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, + 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, + 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, + 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040 +}; + +/** update the crc value with new data. + * @param crc The current crc value. + * @param data Pointer to a buffer of @a data_len bytes. + * @param data_len Number of bytes in the @a data buffer. + * @return The updated crc value. + */ +static uint16_t crc16_update(uint16_t crc, const uint8_t *data, size_t data_len) +{ + const unsigned char *d = (const unsigned char *)data; + unsigned int tbl_idx; + + while (data_len--) { + tbl_idx = (crc ^ *d) & 0xff; + crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffff; + + d++; + } + return crc & 0xffff; +} + +/** SHA-1 input data to calculate MAC for 'Read Authenticated Page' function command */ +static uint32_t m[16] = {0}; +/** intermediate calculation */ +uint32_t wt[80] = {0}; + +/** DS2432 SHA-1 S function, rotating to the left + * @param[in] x value to rotate by @a n to the left + * @param[in] n rotate @a x by n to the left + * @return @a x rotated ny @a n to the left + */ +static uint32_t s_left(uint32_t x, uint8_t n) { + return (((x)<<(n)) | ((x)>>(32-(n)))); +} + +/** DS2432 SHA-1 F function + * @param[in] t time/round + * @param[in] b B value + * @param[in] c C value + * @param[in] d D value + * @return result of the F function + */ +static uint32_t f(uint8_t t, uint32_t b, uint32_t c, uint32_t d) { + if (t<20) { + return (b&c)|((~b)&d); + } else if (t<40) { + return b^c^d; + } else if (t<60) { + return (b&c)|(b&d)|(c&d); + } else if (t<80) { + return b^c^d; + } else { // this should not happen + return 0; + } +} + +/** DS2432 SHA-1 K function + * @param[in] t time/round + * @return result of the K function + */ +static uint32_t k(uint8_t t) { + if (t<20) { + return 0x5A827999; + } else if (t<40) { + return 0x6ED9EBA1; + } else if (t<60) { + return 0x8F1BBCDC; + } else if (t<80) { + return 0xCA62C1D6; + } else { // this should not happen + return 0; + } +} + +/** DS2432 SHA-1 W function + * @param[in] t time/round + * @note uses @a m or previously calculated @a wt values + * @return result of the W function + */ +static uint32_t w(uint8_t t) { + if (t<16) { + return m[t]; + } else { + return s_left(wt[t-3]^wt[t-8]^wt[t-14]^wt[t-16], 1); + } +} + /** program entry point * this is the firmware function started by the micro-controller */ @@ -175,7 +307,6 @@ void main(void) { rcc_clock_setup_in_hse_8mhz_out_72mhz(); // use 8 MHz high speed external clock to generate 72 MHz internal clock - #if DEBUG // enable functionalities for easier debug DBGMCU_CR |= DBGMCU_CR_IWDG_STOP; // stop independent watchdog counter when code is halted @@ -192,7 +323,7 @@ void main(void) board_setup(); // setup board usart_setup(); // setup USART (for printing) usb_cdcacm_setup(); // setup USB CDC ACM (for printing) - printf("welcome to the CuVoodoo STM32F1 1-Wire salve example application\n"); // print welcome message + printf("welcome to the CuVoodoo STM32F1 DS2432 implementation (1k-Bit Protected 1-Wire EEPROM with SHA-1 Engine)\n"); // print welcome message #if !(DEBUG) // show watchdog information @@ -217,43 +348,66 @@ void main(void) time_tm = localtime(&time_rtc); // convert time printf("date: %d-%02d-%02d %02d:%02d:%02d\n", 1900+time_tm->tm_year, time_tm->tm_mon+1, time_tm->tm_mday, time_tm->tm_hour, time_tm->tm_min, time_tm->tm_sec); + uint8_t ds2432_eeprom[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97}; /**< EEPROM content (including secret) */ + uint8_t ds2432_scratchpad[8]; /**< scratchpad data */ + uint8_t ds2432_address[2+1] = {0, 0, 0x5f}; /**< address registers: target address and E/S */ + uint8_t ds2432_buffer[2+1+8+2]; /**< buffer to save command code target address, data status, scratchpad, and CRC */ + const uint8_t ds2432_padding = 0xff; /**< padding byte used in Read Authenticated Page command */ + uint16_t ds2432_crc = 0; // CRC-16 used in 1-Wire DS2432 communication + uint8_t ds2432_mac[20] = {0}; // buffer for the MAC + enum { +DS2432_STATE_IDLE, +DS2432_STATE_WRITE_SCRATCHPAD_DATA, +DS2432_STATE_WRITE_SCRATCHPAD_CRC, +DS2432_STATE_READ_SCRATCHPAD_ADDRESS, +DS2432_STATE_READ_SCRATCHPAD_DATA, +DS2432_STATE_READ_SCRATCHPAD_CRC, +DS2432_STATE_READ_AUTHENTICATED_PAGE_ADDRESS, +DS2432_STATE_READ_AUTHENTICATED_PAGE_DATA, +DS2432_STATE_READ_AUTHENTICATED_PAGE_PADDING, +DS2432_STATE_READ_AUTHENTICATED_PAGE_CRC, +DS2432_STATE_READ_AUTHENTICATED_PAGE_MAC, +DS2432_STATE_READ_AUTHENTICATED_PAGE_MACCRC, +DS2432_STATE_READ_MEMORY_ADDRESS, +DS2432_STATE_READ_MEMORY_DATA, +} ds2432_state = DS2432_STATE_IDLE; /**< current state */ + printf("setup 1-Wire bus: "); - onewire_slave_setup(0xb3, 0x0047414feedb); // setup 1-Wire peripheral to act as slave + onewire_slave_setup(ds2432_eeprom[0x90], ((uint64_t)ds2432_eeprom[0x91]<<0)+((uint64_t)ds2432_eeprom[0x91]<<0)+((uint64_t)ds2432_eeprom[0x92]<<8)+((uint64_t)ds2432_eeprom[0x93]<<16)+((uint64_t)ds2432_eeprom[0x94]<<24)+((uint64_t)ds2432_eeprom[0x95]<<32)+((uint64_t)ds2432_eeprom[0x96]<<40)); // setup 1-Wire peripheral to act as slave printf("OK\n"); - uint8_t onewire_slave_data[2] = {0}; // data to be transferred // main loop printf("command input: ready\n"); bool action = false; // if an action has been performed don't go to sleep button_flag = false; // reset button flag - char c = '\0'; // to store received character + char ch = '\0'; // to store received character bool char_flag = false; // a new character has been received while (true) { // infinite loop iwdg_reset(); // kick the dog while (usart_received) { // data received over UART action = true; // action has been performed led_toggle(); // toggle LED - c = usart_getchar(); // store receive character + ch = usart_getchar(); // store receive character char_flag = true; // notify character has been received } while (usb_cdcacm_received) { // data received over USB action = true; // action has been performed led_toggle(); // toggle LED - c = usb_cdcacm_getchar(); // store receive character + ch = usb_cdcacm_getchar(); // store receive character char_flag = true; // notify character has been received } while (char_flag) { // user data received char_flag = false; // reset flag action = true; // action has been performed - printf("%c",c); // echo receive character - if (c=='\r' || c=='\n') { // end of command received + printf("%c",ch); // echo receive character + if (ch=='\r' || ch=='\n') { // end of command received if (command_i>0) { // there is a command to process command[command_i] = 0; // end string command_i = 0; // prepare for next command process_command(command); // process user command } } else { // user command input - command[command_i] = c; // save command input + command[command_i] = ch; // save command input if (command_itm_hour, time_tm->tm_min, time_tm->tm_sec); } } - while (onewire_slave_function_code_received) { + while (onewire_slave_function_code_received) { // we received a function command code over the 1-Wire bus onewire_slave_function_code_received = false; // reset flag action = true; // action has been performed - printf("1-Wire function command received: 0x%02x\n", onewire_slave_function_code); - if (0x55==onewire_slave_function_code) { // master will write data - onewire_slave_function_read(onewire_slave_data, LENGTH(onewire_slave_data)*8); - } else if (0xf0==onewire_slave_function_code) { // master will read data - onewire_slave_function_write(onewire_slave_data, LENGTH(onewire_slave_data)*8); - } else if (0x23==onewire_slave_function_code) { // master will first write data, then read - onewire_slave_function_read(onewire_slave_data, LENGTH(onewire_slave_data)*8); + switch (onewire_slave_function_code) { + case 0x0f: // Write Scratchpad + onewire_slave_function_read(ds2432_buffer, 2+8); // read target address and scratchpad + ds2432_state = DS2432_STATE_WRITE_SCRATCHPAD_DATA; // update state + break; + case 0xaa: // Read Scratchpad + onewire_slave_function_write(ds2432_address, LENGTH(ds2432_address)); // send address registers + ds2432_state = DS2432_STATE_READ_SCRATCHPAD_ADDRESS; // update state + break; + case 0xa5: // Read Authenticated Page + onewire_slave_function_read(ds2432_buffer, 2); // read target address + ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_ADDRESS; // update state + break; + case 0xf0: // Read Memory + onewire_slave_function_read(ds2432_buffer, 2); // read target address + ds2432_state = DS2432_STATE_READ_MEMORY_ADDRESS; // update state + break; + default: // unknown function command code + ds2432_state = DS2432_STATE_IDLE; // return to idle state + break; } + printf("1-Wire function command received: 0x%02x\n", onewire_slave_function_code); } - while (onewire_slave_transfer_complete) { + while (onewire_slave_transfer_complete) { // the current data transfer completed onewire_slave_transfer_complete = false; // reset flag action = true; // action has been performed - printf("1-Wire transfer complete\n"); - if (0x55==onewire_slave_function_code) { // master wrote data - printf("data read: "); - for (uint8_t i=0; i>0; // save CRC (LSB first) + ds2432_buffer[2+1+8+1] = ds2432_crc>>8; // save CRC (MSB last) + onewire_slave_function_write(&ds2432_buffer[2+1+8+0], 2); // write CRC + ds2432_state = DS2432_STATE_WRITE_SCRATCHPAD_CRC; // update state + ds2432_address[0] = ds2432_buffer[0]&0xf8; // save target address + ds2432_address[1] = ds2432_buffer[1]; // save target address + ds2432_address[2] = 0x5f; // reset state + for (uint8_t i=0; i>0; // save CRC (LSB first) + ds2432_buffer[2+1+8+1] = ds2432_crc>>8; // save CRC (MSB last) + break; + case DS2432_STATE_READ_SCRATCHPAD_DATA: // scratchpad data transfer complete, send CRC + onewire_slave_function_write(&ds2432_buffer[2+1+8+0], 2); // send CRC + ds2432_state = DS2432_STATE_WRITE_SCRATCHPAD_CRC; // update state + break; + case DS2432_STATE_READ_AUTHENTICATED_PAGE_ADDRESS: // target address transfer completed, send data + if (0==ds2432_buffer[1] && ds2432_buffer[0]<0x80) { // target address matches to memory page + onewire_slave_function_write(&ds2432_eeprom[ds2432_buffer[0]], 0x20-(ds2432_buffer[0]&0x1f)); // send memory data until end of page + ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_DATA; // update state + } else { // target address is out of range + ds2432_state = DS2432_STATE_IDLE; // return to idle state + } + break; + case DS2432_STATE_READ_AUTHENTICATED_PAGE_DATA: // memory page data transfer completed, send padding byte + onewire_slave_function_write((uint8_t *)&ds2432_padding, 1); // send padding byte + ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_PADDING; // update state + ds2432_crc = crc16_update(0, (const uint8_t *)&onewire_slave_function_code, 1); // initialize CRC with function code + ds2432_crc = crc16_update(ds2432_crc, ds2432_buffer, 2); // update CRC with target address + ds2432_crc = crc16_update(ds2432_crc, &ds2432_eeprom[ds2432_buffer[0]], 0x20-(ds2432_buffer[0]&0x1f)); // update CRC with data + ds2432_crc = crc16_update(ds2432_crc, &ds2432_padding, 1); // update CRC with padding + ds2432_crc ^= 0xffff; // invert CRC + ds2432_buffer[2+1+8+0] = ds2432_crc>>0; // save CRC (LSB first) + ds2432_buffer[2+1+8+1] = ds2432_crc>>8; // save CRC (MSB last) + break; + case DS2432_STATE_READ_AUTHENTICATED_PAGE_PADDING: // padding byte transfer complete, send CRC + onewire_slave_function_write(&ds2432_buffer[2+1+8+0], 2); // send CRC + ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_CRC; // update state + // calculate MAC + { + ds2432_buffer[0] &= 0xe0; // set target address to start of page + // initialize SHA-1 input data (see table 4) + m[0] = (ds2432_eeprom[0x80+0]<<24)+(ds2432_eeprom[0x80+1]<<16)+(ds2432_eeprom[0x80+2]<<8)+(ds2432_eeprom[0x80+3]<<0); // copy secret + for (uint8_t i=0; i<8; i++) { // copy page + m[1+i] = (ds2432_eeprom[ds2432_buffer[0]+i*4+0]<<24)+(ds2432_eeprom[ds2432_buffer[0]+i*4+1]<<16)+(ds2432_eeprom[ds2432_buffer[0]+i*4+2]<<8)+(ds2432_eeprom[ds2432_buffer[0]+i*4+3]<<0); + } + m[9] = (0xff<<24)+(0xff<<16)+(0xff<<8)+(0xff<<0); // filling bytes + m[10] = ((0x40+(ds2432_buffer[0]>>5))<<24)+(ds2432_eeprom[0x90+0]<<16)+(ds2432_eeprom[0x90+1]<<8)+(ds2432_eeprom[0x90+2]<<0); // copy target and ROM code + m[11] = (ds2432_eeprom[0x90+3]<<24)+(ds2432_eeprom[0x90+4]<<16)+(ds2432_eeprom[0x90+5]<<8)+(ds2432_eeprom[0x90+6]<<0); // copy ROM code + m[12] = (ds2432_eeprom[0x80+4]<<24)+(ds2432_eeprom[0x80+5]<<16)+(ds2432_eeprom[0x80+6]<<8)+(ds2432_eeprom[0x80+7]<<0); // copy rest of secret + m[13] = (ds2432_scratchpad[4]<<24)+(ds2432_scratchpad[5]<<16)+(ds2432_scratchpad[6]<<8)+(0x80<<0); // copy challenge + m[14] = (0x00<<24)+(0x00<<16)+(0x00<<8)+(0x00<<0); + m[15] = (0x00<<24)+(0x00<<16)+(0x01<<8)+(0xb8<<0); + + // initialize variables + uint32_t a = 0x67452301; + uint32_t b = 0xEFCDAB89; + uint32_t c = 0x98BADCFE; + uint32_t d = 0x10325476; + uint32_t e = 0xC3D2E1F0; + + // loop through computation + for (uint8_t t=0; t<80; t++) { + wt[t] = w(t); + uint32_t tmp = s_left(a, 5)+f(t,b,c,d)+wt[t]+k(t)+e; + e = d; + d = c; + c = s_left(b, 30); + b = a; + a = tmp; + } + + // copy result + ds2432_mac[0] = e>>0; + ds2432_mac[1] = e>>8; + ds2432_mac[2] = e>>16; + ds2432_mac[3] = e>>24; + ds2432_mac[4] = d>>0; + ds2432_mac[5] = d>>8; + ds2432_mac[6] = d>>16; + ds2432_mac[7] = d>>24; + ds2432_mac[8] = c>>0; + ds2432_mac[9] = c>>8; + ds2432_mac[10] = c>>16; + ds2432_mac[11] = c>>24; + ds2432_mac[12] = b>>0; + ds2432_mac[13] = b>>8; + ds2432_mac[14] = b>>16; + ds2432_mac[15] = b>>24; + ds2432_mac[16] = a>>0; + ds2432_mac[17] = a>>8; + ds2432_mac[18] = a>>16; + ds2432_mac[19] = a>>24; + } + + break; + case DS2432_STATE_READ_AUTHENTICATED_PAGE_CRC: // CRC transfer completed, send MAC + onewire_slave_function_write(ds2432_mac, LENGTH(ds2432_mac)); // send CRC + ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_MAC; // update state + ds2432_crc = crc16_update(0, ds2432_mac, LENGTH(ds2432_mac)); // calculate CRC for MAC + ds2432_crc ^= 0xffff; // invert CRC + ds2432_buffer[2+1+8+0] = ds2432_crc>>0; // save CRC (LSB first) + ds2432_buffer[2+1+8+1] = ds2432_crc>>8; // save CRC (MSB last) + break; + case DS2432_STATE_READ_AUTHENTICATED_PAGE_MAC: // padding byte transfer complete, send CRC + onewire_slave_function_write(&ds2432_buffer[2+1+8+0], 2); // send CRC + ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_MACCRC; // update state + break; + case DS2432_STATE_READ_MEMORY_ADDRESS: + if (0==ds2432_buffer[1] && ds2432_buffer[0]<0x97) { // target address is in EEPROM range + onewire_slave_function_write(&ds2432_eeprom[ds2432_buffer[0]], LENGTH(ds2432_eeprom)-ds2432_buffer[0]); // send memory data until end of page + ds2432_state = DS2432_STATE_READ_MEMORY_DATA; // update state + } else { // target address is out of range + ds2432_state = DS2432_STATE_IDLE; // return to idle state + } + break; + default: // unknown or end state + ds2432_state = DS2432_STATE_IDLE; // return to idle state + break; } + printf("1-Wire transfer complete\n"); } if (action) { // go to sleep if nothing had to be done, else recheck for activity action = false;