New memory address for i2c dev loaded apps (#2817)

* New memory address for i2c dev loaded apps

* better download handling on error

* new hackrf version (added PortapackRf support)

* lock i2cdev while loading apps
This commit is contained in:
Totoo 2025-10-14 09:45:52 +02:00 committed by GitHub
parent 54d99945f2
commit 2f4d222403
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 52 additions and 10 deletions

View file

@ -132,20 +132,36 @@ namespace ui {
gridItem.on_select = [&nav, appInfo, i]() {
auto dev2 = (i2cdev::I2cDev_PPmod*)i2cdev::I2CDevManager::get_dev_by_model(I2C_DEVMDL::I2CDECMDL_PPMOD);
dev2->lockDevice();
if (dev2) {
auto app_image = reinterpret_cast<uint8_t*>(portapack::memory::map::m4_code.end() - appInfo->binary_size);
// auto app_image = reinterpret_cast<uint8_t*>(portapack::memory::map::m4_code.end() - appInfo->binary_size);
auto app_image = reinterpret_cast<uint8_t*>(portapack::memory::map::local_sram_0.base());
uint8_t errorcnt = 0;
for (size_t j = 0; j < appInfo->binary_size; j += 128) {
errorcnt = 0;
do {
auto segment = dev2->downloadStandaloneApp(i, j);
if (segment.size() != 128) {
continue;
errorcnt++;
if (errorcnt > 5) {
break;
}
} else {
std::copy(segment.begin(), segment.end(), app_image + j);
break;
}
} while (1); // when ok, break. when errorcnt > 5, break
if (errorcnt > 5) {
nav.display_modal("Error", "Unable to download app.");
dev2->unlockDevice();
return;
}
}
if (!run_module_app(nav, app_image, appInfo->binary_size)) {
nav.display_modal("Error", "Unable to run downloaded app.");
}
dev2->unlockDevice();
} else
nav.display_modal("Error", "Unable to download app.");
};
@ -346,7 +362,6 @@ namespace ui {
if (openError)
return false;
// TODO: move this to m4 memory space
auto app_image = reinterpret_cast<uint8_t*>(portapack::memory::map::local_sram_0.base());
// read file in 512 byte chunks

View file

@ -46,6 +46,7 @@ bool I2cDev_PPmod::init(uint8_t addr_) {
}
void I2cDev_PPmod::update() {
if (isLocked()) return; // device is busy
// mask = get_features_mask(); //saved on init. replug device if something changed. //needs to revise when modules come out.
if (mask & (uint64_t)SupportedFeatures::FEAT_GPS && self_timer % SENSORUPDATETIME == 0) {
auto data = get_gps_data();
@ -101,11 +102,13 @@ void I2cDev_PPmod::update() {
}
bool I2cDev_PPmod::get_shell_get_buffer_data(uint8_t* buff, size_t len) {
if (isLocked()) return false; // device is busy
Command cmd = Command::COMMAND_SHELL_MODTOPP_DATA;
return i2c_read((uint8_t*)&cmd, 2, buff, len);
}
std::optional<orientation_t> I2cDev_PPmod::get_orientation_data() {
if (isLocked()) return std::nullopt; // device is busy
Command cmd = Command::COMMAND_GETFEAT_DATA_ORIENTATION;
orientation_t data;
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&data, sizeof(orientation_t));
@ -116,6 +119,7 @@ std::optional<orientation_t> I2cDev_PPmod::get_orientation_data() {
}
std::optional<gpssmall_t> I2cDev_PPmod::get_gps_data() {
if (isLocked()) return std::nullopt; // device is busy
Command cmd = Command::COMMAND_GETFEAT_DATA_GPS;
gpssmall_t data;
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&data, sizeof(gpssmall_t));
@ -126,6 +130,7 @@ std::optional<gpssmall_t> I2cDev_PPmod::get_gps_data() {
}
std::optional<environment_t> I2cDev_PPmod::get_environment_data() {
if (isLocked()) return std::nullopt; // device is busy
Command cmd = Command::COMMAND_GETFEAT_DATA_ENVIRONMENT;
environment_t data;
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&data, sizeof(environment_t));
@ -136,6 +141,7 @@ std::optional<environment_t> I2cDev_PPmod::get_environment_data() {
}
std::optional<uint16_t> I2cDev_PPmod::get_light_data() {
if (isLocked()) return std::nullopt; // device is busy
Command cmd = Command::COMMAND_GETFEAT_DATA_LIGHT;
uint16_t data;
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&data, sizeof(uint16_t));
@ -146,6 +152,7 @@ std::optional<uint16_t> I2cDev_PPmod::get_light_data() {
}
uint16_t I2cDev_PPmod::get_shell_buffer_bytes() {
if (isLocked()) return 0; // device is busy
Command cmd = Command::COMMAND_SHELL_MODTOPP_DATA_SIZE;
uint16_t data;
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&data, sizeof(uint16_t));
@ -156,6 +163,7 @@ uint16_t I2cDev_PPmod::get_shell_buffer_bytes() {
}
uint64_t I2cDev_PPmod::get_features_mask() {
if (isLocked()) return 0; // device is busy
uint64_t mask_ = 0;
Command cmd = Command::COMMAND_GETFEATURE_MASK;
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&mask_, sizeof(mask_));
@ -170,6 +178,7 @@ uint64_t I2cDev_PPmod::get_features_mask() {
}
std::optional<I2cDev_PPmod::device_info> I2cDev_PPmod::readDeviceInfo() {
if (isLocked()) return std::nullopt; // device is busy
Command cmd = Command::COMMAND_INFO;
I2cDev_PPmod::device_info info;

View file

@ -108,6 +108,19 @@ FROM HERE YOU SHOULDN'T WRITE ANYTHING IF YOU JUST IMPLEMENT A NEW DRIVER
*/
void I2cDev::unlockDevice() {
mtx = 0;
}
// when device is locked, all not important queries will return 0 or nullopt, so no communication broken.
bool I2cDev::lockDevice() {
if (mtx == 0) {
mtx = 1;
return true;
}
return false;
}
void I2cDev::set_update_interval(uint8_t interval) {
query_interval = interval;
}

View file

@ -41,7 +41,7 @@ namespace i2cdev {
class I2cDev {
public:
virtual ~I2cDev(){};
virtual bool init(uint8_t addr); // returns true if it is that that device we are looking for.
virtual bool init(uint8_t addr) = 0; // returns true if it is that that device we are looking for.
virtual void update() = 0; // override this, and you'll be able to query your device and broadcast the result to the system
void set_update_interval(uint8_t interval); // sets the device's update interval in sec. if you change it, don't forget to change back to it's original value after you finished!
@ -59,6 +59,10 @@ class I2cDev {
int16_t readS16_LE_1(uint8_t reg);
uint32_t read24_1(uint8_t reg);
bool lockDevice(); // locks the device's "mutex". returns true on success. guard important communication with this
void unlockDevice(); // unlocks the device's "mutex"
inline bool isLocked() { return mtx != 0; }
bool need_del = false; // device can self destruct, and re-init when new scan discovers it
I2C_DEVMDL model = I2CDEVMDL_NOTSET; // overwrite it in the init()!!!
uint8_t query_interval = 5; // in seconds. can be overriden in init() if necessary
@ -68,6 +72,7 @@ class I2cDev {
uint8_t addr = 0; // some devices can have different addresses, so we store what was it wound with
uint8_t errcnt = 0; // error count during communication. if it reaches a threshold set need_del to remove itself from the device list
uint8_t mtx = 0; // internal lock, so important client code can be skipped when lock is on. check PPMod for an example
};
// store for the devices. may not have a driver if not supported

2
hackrf

@ -1 +1 @@
Subproject commit 651d0a7f232e12016b3b12fb6a9b3fea08eb52fd
Subproject commit 03e4732a5308a3d0de5b0341004d7a2fcc825806