static uint32_t hal_storage_i2c_write_buffer(uint8_t address, uint8_t *buffer, uint8_t len) { if (HAL_STORAGE_I2C_DEBUG) { debug("hal_storage: i2c write_buffer(0x"); debug_put_hex8(address>>8); debug_put_hex8(address&0xFF); debug(", ..., "); debug_put_uint16(len); debug(")\n"); debug_flush(); } uint8_t i; // check for out of bound condition uint16_t last_byte = (uint16_t)address + (uint16_t) len; if (last_byte > 255) { debug("hal_storage: ERROR write request invalid. out of memory!\n"); debug_flush(); return 0; } // write data for (i = 0; i < len; i++) { if (!hal_storage_i2c_write_byte(address + i, buffer[i])) { return 0; } } return 1; }
static void telemetry_rx_echo_test(void){ // just for testing purposes... volatile EXTERNAL_MEMORY uint8_t data; while(1){ wdt_reset(); if (telemetry_pop(&data)){ // debug_putc(data); debug_putc(' '); debug_put_hex8(data); if (data == 0x5E) debug_put_newline(); } } }
// single byte write is slow and ugly but will do // we only use this once during binding... static uint32_t hal_storage_i2c_write_byte(uint8_t address, uint8_t data) { if (HAL_STORAGE_I2C_DEBUG) { debug("hal_storage: i2c write_byte(0x"); debug_put_hex8(address>>8); debug_put_hex8(address&0xFF); debug(", 0x"); debug_put_hex8(data); debug(")\n"); debug_flush(); } timeout_set(EEPROM_I2C_TIMEOUT); while (I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BUSY)) { if (timeout_timed_out()) { debug("hal_i2c: bus busy... timeout!\n"); return 0; } } // send start I2C_GenerateSTART(EEPROM_I2C, ENABLE); // set on EV5 and clear it (cleared by reading SR1 then writing to DR) timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { if (timeout_timed_out()) { debug("hal_i2c: master flag error... timeout!\n"); return 0; } } // send EEPROM address for write I2C_Send7bitAddress(EEPROM_I2C, EEPROM_I2C_ADDRESS, I2C_Direction_Transmitter); // test on EV6 and clear it timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if (timeout_timed_out()) { debug("hal_i2c: transmitter flag error... timeout!\n"); return 0; } } // send the EEPROM's internal address to write to I2C_SendData(EEPROM_I2C, address); // test on EV8 and clear it timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { if (timeout_timed_out()) { debug("hal_i2c: address tx error... timeout!\n"); return 0; } } // send data byte I2C_SendData(EEPROM_I2C, data); // test on EV8 and clear it timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { if (timeout_timed_out()) { debug("hal_i2c: data tx error... timeout!\n"); return 0; } } // stop transmission // clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */ (void)EEPROM_I2C->SR2; // send STOP Condition I2C_GenerateSTOP(EEPROM_I2C, ENABLE); // wait to make sure that STOP control bit has been cleared timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (EEPROM_I2C->CR1 & I2C_CR1_STOP) { if (timeout_timed_out()) { debug("hal_i2c: stop flag error... timeout!\n"); return 0; } } // wait for write cycle time (5ms) delay_ms(5+1); if (HAL_STORAGE_I2C_DEBUG) { debug("hal_storage: write done\n"); debug_flush(); } return 1; }
static uint32_t hal_storage_i2c_read_buffer(uint16_t address, uint8_t *buffer, uint8_t len) { if (HAL_STORAGE_I2C_DEBUG) { debug("hal_storage: i2c read_buffer(0x"); debug_put_hex8(address>>8); debug_put_hex8(address&0xFF); debug(", ..., "); debug_put_uint16(len); debug(")\n"); debug_flush(); } timeout_set(EEPROM_I2C_TIMEOUT); while (I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BUSY)) { if (timeout_timed_out()) { debug("hal_i2c: bus busy... timeout!\n"); return 0; } } // send start I2C_GenerateSTART(EEPROM_I2C, ENABLE); // set on EV5 and clear it (cleared by reading SR1 then writing to DR) timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { if (timeout_timed_out()) { debug("hal_i2c: master flag error... timeout!\n"); return 0; } } // send EEPROM address for write I2C_Send7bitAddress(EEPROM_I2C, EEPROM_I2C_ADDRESS, I2C_Direction_Transmitter); // test on EV6 and clear it timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if (timeout_timed_out()) { debug("hal_i2c: transmitter flag error... timeout!\n"); return 0; } } // send the EEPROM's internal address to read from: Only one byte address I2C_SendData(EEPROM_I2C, address); // test on EV8 and clear it timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (!I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BTF) == RESET) { if (timeout_timed_out()) { debug("hal_i2c: btf flag error... timeout!\n"); return 0; } } // send START condition a second time I2C_GenerateSTART(EEPROM_I2C, ENABLE); // set on EV5 and clear it (cleared by reading SR1 then writing to DR) timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { if (timeout_timed_out()) { debug("hal_i2c: master flag error... timeout!\n"); return 0; } } // send address (READ) I2C_Send7bitAddress(EEPROM_I2C, EEPROM_I2C_ADDRESS, I2C_Direction_Receiver); // test on EV6 and clear it timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { if (timeout_timed_out()) { debug("hal_i2c: receiver flag error... timeout!\n"); return 0; } } if (HAL_STORAGE_I2C_DEBUG) { debug("hal_storage: reading "); debug_put_uint8(len); debug("bytes: "); debug_flush(); } // do not use dma etc, we do not need highspeed. do polling: uint16_t i; for (i = 0; i < len; i++) { // wait on ADDR flag to be set (ADDR is still not cleared at this level) timeout_set(EEPROM_I2C_FLAG_TIMEOUT); /* Test on EV7 and clear it */ while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)) { if (timeout_timed_out()) { debug("hal_i2c: byte rx error... timeout!\n"); return 0; } } // read byte received: buffer[i] = I2C_ReceiveData(EEPROM_I2C); if (HAL_STORAGE_I2C_DEBUG) { debug_put_hex8(buffer[i]); debug_putc(' '); debug_flush(); } if (i == (len-1)) { // last byte? -> NACK I2C_AcknowledgeConfig(EEPROM_I2C, DISABLE); } else { // more bytes -> ACK I2C_AcknowledgeConfig(EEPROM_I2C, ENABLE); } // wait for read to finish timeout_set(EEPROM_I2C_FLAG_TIMEOUT*100); while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_SLAVE_BYTE_RECEIVED)) { // while (I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_RXNE) == RESET) { if (timeout_timed_out()) { debug("hal_i2c: read error... timeout!\n"); return 0; } } } // stop transmission // clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */ (void)EEPROM_I2C->SR2; // send STOP Condition I2C_GenerateSTOP(EEPROM_I2C, ENABLE); if (HAL_STORAGE_I2C_DEBUG) { debug(". done.\n"); debug_flush(); } // wait to make sure that STOP control bit has been cleared timeout_set(EEPROM_I2C_FLAG_TIMEOUT); while (EEPROM_I2C->CR1 & I2C_CR1_STOP) { if (timeout_timed_out()) { debug("hal_i2c: stop flag error... timeout!\n"); return 0; } } // re-enable Acknowledgement to be ready for another reception I2C_AcknowledgeConfig(EEPROM_I2C, ENABLE); if (HAL_STORAGE_I2C_DEBUG) { debug("hal_storage: read done\n"); debug_flush(); } return 1; }