void read_eeprom(void) { uint16_t addr, i; uint8_t len; uint8_t buf[64]; uint8_t result; /*get address*/ addr = mcs_recv(); addr <<= 8; addr |= mcs_recv(); /*get length*/ len = mcs_recv(); /*read eeprom*/ result = i2c_eeprom_read(EEPROM_DEV, addr, buf, len); for(i=0; i<len; i++) mcs_send(buf[i]); if(result == EEPROM_OK) mcs_send(EEPROM_DONE); else mcs_send(BAD_EEPROM); }
int red_extension_read_ethernet_config(I2CEEPROM *i2c_eeprom, ExtensionEthernetConfig *ethernet_config) { if (i2c_eeprom_read(i2c_eeprom, EXTENSION_EEPROM_ETHERNET_MAC_ADDRESS, ethernet_config->mac, EXTENSION_ETHERNET_MAC_SIZE) < EXTENSION_ETHERNET_MAC_SIZE) { log_warn("Can't read MAC address, using default address"); ethernet_config->mac[0] = 0x40; ethernet_config->mac[1] = 0xD8; ethernet_config->mac[2] = 0x55; ethernet_config->mac[3] = 0x02; ethernet_config->mac[4] = 0xA1; ethernet_config->mac[5] = 0x00; return -1; } return 0; }
// Init function called from central brickd code int rs485_extension_init(void) { uint8_t _tmp_eeprom_read_buf[4]; int _eeprom_read_status; int phase = 0; log_info("RS485: Checking presence of extension"); // Modbus config: TYPE _eeprom_read_status = i2c_eeprom_read((uint16_t)RS485_EXTENSION_MODBUS_CONFIG_LOCATION_TYPE, _tmp_eeprom_read_buf, 4); if (_eeprom_read_status <= 0) { log_error("RS485: EEPROM read error. Most probably no RS485 extension present"); return 0; } _modbus_serial_config_type = (uint32_t)((_tmp_eeprom_read_buf[0] << 0) | (_tmp_eeprom_read_buf[1] << 8) | (_tmp_eeprom_read_buf[2] << 16) | (_tmp_eeprom_read_buf[3] << 24)); if (_modbus_serial_config_type == RS485_EXTENSION_TYPE) { log_info("RS485: Initializing extension subsystem"); // Create base stack if(stack_create(&_rs485_extension.base, "rs485_extension", (StackDispatchRequestFunction)rs485_extension_dispatch_to_modbus) < 0) { log_error("RS485: Could not create base stack for extension: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 1; // Add to stacks array if(hardware_add_stack(&_rs485_extension.base) < 0) { goto cleanup; } phase = 2; // Initialize modbus packet queue if(queue_create(&_rs485_extension.packet_to_modbus_queue, sizeof(RS485ExtensionPacket)) < 0) { log_error("RS485: Could not create Modbus queue: %s (%d)", get_errno_name(errno), errno); goto cleanup; } // Reading and storing eeprom config // Modbus config: ADDRESS _eeprom_read_status = i2c_eeprom_read((uint16_t)RS485_EXTENSION_MODBUS_CONFIG_LOCATION_ADDRESS, _tmp_eeprom_read_buf, 4); if (_eeprom_read_status <= 0) { log_error("RS485: Could not read config ADDRESS from EEPROM"); goto cleanup; } _modbus_serial_config_address = (uint32_t)((_tmp_eeprom_read_buf[0] << 0) | (_tmp_eeprom_read_buf[1] << 8) | (_tmp_eeprom_read_buf[2] << 16) | (_tmp_eeprom_read_buf[3] << 24)); // Modbus config: BAUDRATE _eeprom_read_status = i2c_eeprom_read((uint16_t)RS485_EXTENSION_MODBUS_CONFIG_LOCATION_BAUDRATE, _tmp_eeprom_read_buf, 4); if (_eeprom_read_status <= 0) { log_error("RS485: Could not read config BAUDRATE from EEPROM"); goto cleanup; } _modbus_serial_config_baudrate = (uint32_t)((_tmp_eeprom_read_buf[0] << 0) | (_tmp_eeprom_read_buf[1] << 8) | (_tmp_eeprom_read_buf[2] << 16) | (_tmp_eeprom_read_buf[3] << 24)); // Modbus config: PARITY _eeprom_read_status = i2c_eeprom_read((uint16_t)RS485_EXTENSION_MODBUS_CONFIG_LOCATION_PARTIY, _tmp_eeprom_read_buf, 1); if (_eeprom_read_status <= 0) { log_error("RS485: Could not read config PARITY from EEPROM"); goto cleanup; } if(_tmp_eeprom_read_buf[0] == RS485_EXTENSION_SERIAL_PARITY_NONE) { _modbus_serial_config_parity = RS485_EXTENSION_SERIAL_PARITY_NONE; } else if (_tmp_eeprom_read_buf[0] == RS485_EXTENSION_SERIAL_PARITY_EVEN){ _modbus_serial_config_parity = RS485_EXTENSION_SERIAL_PARITY_EVEN; } else { _modbus_serial_config_parity = RS485_EXTENSION_SERIAL_PARITY_ODD; } // Modbus config: STOPBITS _eeprom_read_status = i2c_eeprom_read((uint16_t)RS485_EXTENSION_MODBUS_CONFIG_LOCATION_STOPBITS, _tmp_eeprom_read_buf, 1); if (_eeprom_read_status <= 0) { log_error("RS485: Could not read config STOPBITS from EEPROM"); goto cleanup; } _modbus_serial_config_stopbits = _tmp_eeprom_read_buf[0]; // Modbus config (if master): SLAVE ADDRESSES if(_modbus_serial_config_address == 0) { _rs485_extension.slave_num = 0; uint16_t _current_eeprom_location = RS485_EXTENSION_MODBUS_CONFIG_LOCATION_SLAVE_ADDRESSES_START; uint32_t _current_slave_address; _rs485_extension.slave_num = 0; do { _eeprom_read_status = i2c_eeprom_read(_current_eeprom_location, _tmp_eeprom_read_buf, 4); if (_eeprom_read_status <= 0) { log_error("RS485: Could not read config SLAVE ADDRESSES from EEPROM"); goto cleanup; } _current_slave_address = (uint32_t)((_tmp_eeprom_read_buf[0] << 0) | (_tmp_eeprom_read_buf[1] << 8) | (_tmp_eeprom_read_buf[2] << 16) | (_tmp_eeprom_read_buf[3] << 24)); if(_current_slave_address != 0) { _rs485_extension.slaves[_rs485_extension.slave_num] = _current_slave_address; _rs485_extension.slave_num ++; } _current_eeprom_location = _current_eeprom_location + 4; } while(_current_slave_address != 0 && _rs485_extension.slave_num < RS485_EXTENSION_MODBUS_MAX_SLAVES); } // Configuring serial interface from the configs if(rs485_extension_serial_init(RS485_EXTENSION_SERIAL_DEVICE) < 0) { goto cleanup; } // Initial RS485 TX/RX state init_tx_rx_state(); phase = 3; // Setup partial data receive timer setup_timer(&partial_receive_timer, TIME_UNIT_NSEC, PARTIAL_RECEIVE_TIMEOUT); _partial_receive_timeout_event = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); if(!(_partial_receive_timeout_event < 0)) { if(event_add_source(_partial_receive_timeout_event, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, partial_receive_timeout_handler, NULL) < 0) { log_error("RS485: Could not add partial receive timeout notification pipe as event source"); goto cleanup; } } else { log_error("RS485: Could not create partial receive timer"); goto cleanup; } phase = 4; // Adding serial data available event if(event_add_source(_rs485_serial_fd, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, rs485_serial_data_available_handler, NULL) < 0) { log_error("RS485: Could not add new serial data event"); goto cleanup; } phase = 5; // Setup master retry timer setup_timer(&master_retry_timer, TIME_UNIT_NSEC, MASTER_RETRY_TIMEOUT); _master_retry_event = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); if(!(_master_retry_event < 0)) { if(event_add_source(_master_retry_event, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, master_retry_timeout_handler, NULL) < 0) { log_error("RS485: Could not add Modbus master retry notification pipe as event source"); goto cleanup; } } else { log_error("RS485: Could not create Modbus master retry timer"); goto cleanup; } phase = 6; // Setup send verify timer setup_timer(&send_verify_timer, TIME_UNIT_NSEC, SEND_VERIFY_TIMEOUT); _send_verify_event = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); if(!(_send_verify_event < 0)) { if(event_add_source(_send_verify_event, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, send_verify_timeout_handler, NULL) < 0) { log_error("RS485: Could not add Modbus send verify notification pipe as event source"); goto cleanup; } } else { log_error("RS485: Could not create Modbus send verify timer"); goto cleanup; } phase = 7; // Get things going in case of a master if(_modbus_serial_config_address == 0 && _rs485_extension.slave_num > 0) { // Setup master poll slave timer setup_timer(&master_poll_slave_timer, TIME_UNIT_NSEC, MASTER_POLL_SLAVE_TIMEOUT); _master_poll_slave_event = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); if(!(_master_poll_slave_event < 0) ) { if(event_add_source(_master_poll_slave_event, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, master_poll_slave_timeout_handler, NULL) < 0) { log_error("RS485: Could not add Modbus master poll slave notification pipe as event source"); goto cleanup; } } else { log_error("RS485: Could not create Modbus master poll slave timer"); goto cleanup; } master_poll_slave_timeout_handler(NULL); } phase = 8; _initialized = true; } else { log_info("RS485: Extension not present"); goto cleanup; } cleanup: switch (phase) { // no breaks, all cases fall through intentionally case 7: close(_send_verify_event); event_remove_source(_send_verify_event, EVENT_SOURCE_TYPE_GENERIC); case 6: close(_master_retry_event); event_remove_source(_master_retry_event, EVENT_SOURCE_TYPE_GENERIC); case 5: close(_rs485_serial_fd); event_remove_source(_rs485_serial_fd, EVENT_SOURCE_TYPE_GENERIC); case 4: close(_partial_receive_timeout_event); event_remove_source(_partial_receive_timeout_event, EVENT_SOURCE_TYPE_GENERIC); case 3: queue_destroy(&_rs485_extension.packet_to_modbus_queue, NULL); case 2: hardware_remove_stack(&_rs485_extension.base); case 1: stack_destroy(&_rs485_extension.base); default: break; } return phase == 8 ? 0 : -1; }
int red_extension_init(void) { uint8_t buf[4]; int i, j, ret; ExtensionBaseConfig base_config[2]; // First we remove the Ethernet Extension kernel module (if there is one) // to make sure that there isn't a collision between SPI select and I2C select. red_ethernet_extension_rmmod(); // Then we deselect all EEPROMS for (i = 0; i < EXTENSION_NUM_MAX; i++) { for (j = 0; j < extension_startup.num_configs; j++) { red_extension_configure_pin(&extension_startup.config[j], i); } } // Now we can try to find the configurations for (i = 0; i < EXTENSION_NUM_MAX; i++) { I2CEEPROM i2c_eeprom; log_debug("Checking for presence of Extension at position %d", i); int eeprom_length = 0; uint8_t eeprom_buffer[EEPROM_SIZE]; base_config[i].extension = i; base_config[i].type = EXTENSION_TYPE_NONE; if (i2c_eeprom_create(&i2c_eeprom, i) < 0) { return -1; } if ((eeprom_length = red_extension_read_eeprom_from_fs(eeprom_buffer, i)) > 2) { int start_addr = eeprom_buffer[0] | (eeprom_buffer[1] << 8); if (eeprom_length + start_addr >= EEPROM_SIZE) { log_warn("Found malformed EEPROM config (start=%d, length=%d) for extension %d", start_addr, eeprom_length, i); } else { log_info("Found new EEPROM config (start=%d, length=%d) for extension %d", start_addr, eeprom_length, i); if (i2c_eeprom_write(&i2c_eeprom, start_addr, eeprom_buffer+2, eeprom_length-2) < 0) { log_warn("Writing EEPROM config for extension %d failed", i); } else { log_debug("Wrote EEPROM config (start=%d, length=%d) for extension %d", start_addr, eeprom_length, i); } } } if (i2c_eeprom_read(&i2c_eeprom, EXTENSION_EEPROM_TYPE_LOCATION, buf, EXTENSION_EEPROM_TYPE_SIZE) < EXTENSION_EEPROM_TYPE_SIZE) { log_info("Could not find Extension at position %d", i); continue; } base_config[i].type = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); // If there is an extension that is either not configured (Extension type NONE) // Or that we currently don't support (WIFI), we will log it, but try to // continue finding extensions. We can support an extension at position 1 if // there is an unsupported extension at position 0. if (base_config[i].type == EXTENSION_TYPE_NONE) { log_warn("Could not find Extension at position %d (Type None)", i); continue; } if ((base_config[i].type != EXTENSION_TYPE_ETHERNET) && (base_config[i].type != EXTENSION_TYPE_RS485)) { log_warn("Extension at position %d not supported (type %d)", i, base_config[i].type); continue; } switch (base_config[i].type) { case EXTENSION_TYPE_RS485: ret = red_extension_read_rs485_config(&i2c_eeprom, (ExtensionRS485Config *) &base_config[i]); i2c_eeprom_destroy(&i2c_eeprom); if (ret < 0) { log_warn("Could not read RS485 config, ignoring extension at position %d", i); continue; } if (red_extension_save_rs485_config_to_fs((ExtensionRS485Config *) &base_config[i]) < 0) { log_warn("Could not save RS485 config. RS485 Extension at position %d will not show up in Brick Viewer", i); } break; case EXTENSION_TYPE_ETHERNET: ret = red_extension_read_ethernet_config(&i2c_eeprom, (ExtensionEthernetConfig *) &base_config[i]); i2c_eeprom_destroy(&i2c_eeprom); if (ret < 0) { log_warn("Could not read Ethernet config, ignoring extension at position %d", i); continue; } if (red_extension_save_ethernet_config_to_fs((ExtensionEthernetConfig *) &base_config[i]) < 0) { log_warn("Could not save Ethernet config. Ethernet Extension at position %d will not show up in Brick Viewer", i); } break; } } // Configure the pins and initialize extensions for (i = 0; i < EXTENSION_NUM_MAX; i++) { switch (base_config[i].type) { case EXTENSION_TYPE_RS485: log_info("Found RS485 Extension at position %d", i); for (j = 0; j < extension_rs485_pin_config.num_configs; j++) { red_extension_configure_pin(&extension_rs485_pin_config.config[j], i); } if (red_rs485_extension_init((ExtensionRS485Config *) &base_config[i]) < 0) { continue; } _red_extension_type[i] = EXTENSION_TYPE_RS485; break; case EXTENSION_TYPE_ETHERNET: log_info("Found Ethernet Extension at position %d", i); for (j = 0; j < extension_ethernet_pin_config.num_configs; j++) { red_extension_configure_pin(&extension_ethernet_pin_config.config[j], i); } if (red_ethernet_extension_init((ExtensionEthernetConfig *) &base_config[i]) < 0) { continue; } _red_extension_type[i] = EXTENSION_TYPE_ETHERNET; break; } } return 0; }
int red_extension_read_rs485_config(I2CEEPROM *i2c_eeprom, ExtensionRS485Config *rs485_config) { uint8_t buf[4]; // Config: ADDRESS if (i2c_eeprom_read(i2c_eeprom, EXTENSION_EEPROM_RS485_ADDRESS_LOCATION, buf, 4) < 4) { log_error("RS485: Could not read config ADDRESS from EEPROM"); return -1; } rs485_config->address = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); // Config: BAUDRATE if (i2c_eeprom_read(i2c_eeprom, EXTENSION_EEPROM_RS485_BAUDRATE_LOCATION, buf, 4) < 4) { log_error("RS485: Could not read config BAUDRATE from EEPROM"); return -1; } rs485_config->baudrate = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); if (rs485_config->baudrate < 8) { log_error("RS485: Configured baudrate is too low"); return -1; } // Config: PARITY if (i2c_eeprom_read(i2c_eeprom, EXTENSION_EEPROM_RS485_PARTIY_LOCATION, buf, 1) < 1) { log_error("RS485: Could not read config PARITY from EEPROM"); return -1; } if (buf[0] == RS485_EXTENSION_SERIAL_PARITY_NONE) { rs485_config->parity = RS485_EXTENSION_SERIAL_PARITY_NONE; } else if (buf[0] == RS485_EXTENSION_SERIAL_PARITY_EVEN){ rs485_config->parity = RS485_EXTENSION_SERIAL_PARITY_EVEN; } else { rs485_config->parity = RS485_EXTENSION_SERIAL_PARITY_ODD; } // Config: STOPBITS if (i2c_eeprom_read(i2c_eeprom, EXTENSION_EEPROM_RS485_STOPBITS_LOCATION, buf, 1) < 1) { log_error("RS485: Could not read config STOPBITS from EEPROM"); return -1; } rs485_config->stopbits = buf[0]; // Config (if master): SLAVE ADDRESSES if (rs485_config->address == 0) { rs485_config->slave_num = 0; uint16_t current_eeprom_location = EXTENSION_EEPROM_RS485_SLAVE_ADDRESSES_START_LOCATION; uint32_t current_slave_address; rs485_config->slave_address[0] = 0; while (rs485_config->slave_num < EXTENSION_RS485_SLAVES_MAX) { // Config: SLAVE ADDRESS if (i2c_eeprom_read(i2c_eeprom, current_eeprom_location, buf, 4) < 4) { log_error("RS485: Could not read config SLAVE ADDRESSES from EEPROM"); return -1; } current_slave_address = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); rs485_config->slave_address[rs485_config->slave_num] = current_slave_address; if (current_slave_address == 0) { break; } rs485_config->slave_num++; current_eeprom_location += 4; } } else { log_error("RS485: Only master mode supported"); return -1; } return 0; }
uint32_t send_data_stream_ble(ble_luxsync_t * p_luxsync, uint8_t fetchData, uint8_t init) { static uint8_t databuffer[READ_LENGTH+10]; static uint32_t currentPosition = 0; static uint32_t stopPosition = 0; static uint32_t remainingData = 0; static uint16_t read_length; uint32_t err_code = NRF_SUCCESS; static uint32_t endOfChunk = 0; static int x = 0; if ( init ) { currentPosition = 0; stopPosition = eeprom_find_add_pointer(); remainingData = 0; } if ( fetchData ) { print("Getting more data\r\n"); endOfChunk = currentPosition + READ_LENGTH * CHUNKS_PER_TRANSFER; } if ( currentPosition < endOfChunk ) fetchData = 1; do { if ( remainingData <= 0 && fetchData ) { if ( (stopPosition - currentPosition) < READ_LENGTH ) read_length = stopPosition - currentPosition; else read_length = READ_LENGTH; if ( !(i2c_eeprom_read(currentPosition,databuffer, read_length)) ) { err_code = 0xDB; //Memory not read } else { print("*[%d]", currentPosition); remainingData = read_length; currentPosition += read_length; } } print("."); while(remainingData > 0 ) //< read_length) { err_code=ble_luxsync_write_update(p_luxsync,databuffer+(read_length-remainingData),WRITE_LENGTH); if ( err_code== NRF_SUCCESS|| err_code==BLE_ERROR_GATTS_SYS_ATTR_MISSING|| err_code==NRF_ERROR_INVALID_STATE) { // Ignore error. // m_remaining_data =(m_remaining_data+write_lenth); remainingData -= WRITE_LENGTH; } else if (err_code==BLE_ERROR_NO_TX_BUFFERS ) { //print(".[%d]", remainingData); break; } else { // APP_ERROR_HANDLER(err_code); } } print("/"); print("%d %d %d\r\n", currentPosition, endOfChunk, stopPosition); } while( currentPosition < endOfChunk && currentPosition < stopPosition && err_code != BLE_ERROR_NO_TX_BUFFERS ); print("E"); // nrf_gpio_pin_set(MEMORY_LED_PIN_NO); /// debug //if (m_remaining_data>=read_length1) if ( currentPosition >= stopPosition ) { // nrf_delay_ms(50); err_code = ble_luxsync_ACK_update(p_luxsync,0x04); //• Once all the data is sent it changes sync ACk to 0x04 indicating end of data stream if ( err_code== NRF_SUCCESS|| err_code==BLE_ERROR_GATTS_SYS_ATTR_MISSING|| err_code==NRF_ERROR_INVALID_STATE) { // Ignore error. nrf_gpio_pin_set(MEMORY_LED_PIN_NO); flag_send_data=false; print("DONE transmitting\r\n"); //timers_start(); } /* else if (err_code==BLE_ERROR_NO_TX_BUFFERS ) { // break; } else { APP_ERROR_HANDLER(err_code); } */ } return err_code; }
int red_extension_read_rs485_config(I2CEEPROM *i2c_eeprom, ExtensionRS485Config *rs485_config) { uint8_t buf[4]; // address if (i2c_eeprom_read(i2c_eeprom, EXTENSION_EEPROM_RS485_ADDRESS_LOCATION, buf, 4) < 4) { log_error("Could not read RS485 address from EEPROM"); return -1; } rs485_config->address = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); // baudrate if (i2c_eeprom_read(i2c_eeprom, EXTENSION_EEPROM_RS485_BAUDRATE_LOCATION, buf, 4) < 4) { log_error("Could not read RS485 baudrate from EEPROM"); return -1; } rs485_config->baudrate = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); if (rs485_config->baudrate < 8) { log_error("Configured RS485 baudrate is too low"); return -1; } // parity if (i2c_eeprom_read(i2c_eeprom, EXTENSION_EEPROM_RS485_PARTIY_LOCATION, buf, 1) < 1) { log_error("Could not read RS485 parity from EEPROM"); return -1; } if (buf[0] == RS485_EXTENSION_SERIAL_PARITY_NONE) { rs485_config->parity = RS485_EXTENSION_SERIAL_PARITY_NONE; } else if (buf[0] == RS485_EXTENSION_SERIAL_PARITY_EVEN){ rs485_config->parity = RS485_EXTENSION_SERIAL_PARITY_EVEN; } else { rs485_config->parity = RS485_EXTENSION_SERIAL_PARITY_ODD; } // stopbits if (i2c_eeprom_read(i2c_eeprom, EXTENSION_EEPROM_RS485_STOPBITS_LOCATION, buf, 1) < 1) { log_error("Could not read RS485 stopbits from EEPROM"); return -1; } rs485_config->stopbits = buf[0]; // slave addresses if (rs485_config->address == 0) { rs485_config->slave_num = 0; uint16_t current_eeprom_location = EXTENSION_EEPROM_RS485_SLAVE_ADDRESSES_START_LOCATION; uint32_t current_slave_address; rs485_config->slave_address[0] = 0; while (rs485_config->slave_num < EXTENSION_RS485_SLAVES_MAX) { if (i2c_eeprom_read(i2c_eeprom, current_eeprom_location, buf, 4) < 4) { log_error("Could not read RS485 slave addresses from EEPROM"); return -1; } current_slave_address = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); rs485_config->slave_address[rs485_config->slave_num] = current_slave_address; if (current_slave_address == 0) { break; } rs485_config->slave_num++; current_eeprom_location += 4; } } return 0; }