Fix race conditions during sleep/wakeup, where SPI/TWI could be disabled while transaction were in progress (https://github.com/JF002/Pinetime/issues/60).

This commit is contained in:
JF 2020-09-13 21:26:44 +02:00
parent d757344f1b
commit 20f5b0ffba
3 changed files with 34 additions and 18 deletions

View File

@ -105,22 +105,33 @@ void SystemTask::Work() {
Messages message = static_cast<Messages >(msg);
switch(message) {
case Messages::GoToRunning:
isSleeping = false;
spi.Wakeup();
twiMaster.Wakeup();
spiNorFlash.Wakeup();
lcd.Wakeup();
touchPanel.Wakeup();
displayApp->PushMessage(Applications::DisplayApp::Messages::GoToRunning);
displayApp->PushMessage(Applications::DisplayApp::Messages::UpdateBatteryLevel);
xTimerStart(idleTimer, 0);
nimbleController.StartAdvertising();
isSleeping = false;
isWakingUp = false;
break;
case Messages::GoToSleep:
isGoingToSleep = true;
NRF_LOG_INFO("[SystemTask] Going to sleep");
xTimerStop(idleTimer, 0);
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::GoToSleep);
isSleeping = true;
break;
case Messages::OnNewTime:
ReloadIdleTimer();
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::UpdateDateTime);
break;
case Messages::OnNewNotification:
if(isSleeping) GoToRunning();
if(isSleeping && !isWakingUp) GoToRunning();
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::NewNotification);
break;
case Messages::BleConnected:
@ -130,7 +141,7 @@ void SystemTask::Work() {
break;
case Messages::BleFirmwareUpdateStarted:
doNotGoToSleep = true;
if(isSleeping) GoToRunning();
if(isSleeping && !isWakingUp) GoToRunning();
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::BleFirmwareUpdateStarted);
break;
case Messages::BleFirmwareUpdateFinished:
@ -152,6 +163,8 @@ void SystemTask::Work() {
spi.Sleep();
twiMaster.Sleep();
isSleeping = true;
isGoingToSleep = false;
break;
default: break;
}
@ -180,31 +193,27 @@ void SystemTask::Work() {
}
void SystemTask::OnButtonPushed() {
if(isGoingToSleep) return;
if(!isSleeping) {
NRF_LOG_INFO("[SystemTask] Button pushed");
PushMessage(Messages::OnButtonEvent);
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::ButtonPushed);
}
else {
NRF_LOG_INFO("[SystemTask] Button pushed, waking up");
GoToRunning();
if(!isWakingUp) {
NRF_LOG_INFO("[SystemTask] Button pushed, waking up");
GoToRunning();
}
}
}
void SystemTask::GoToRunning() {
isWakingUp = true;
PushMessage(Messages::GoToRunning);
spi.Wakeup();
twiMaster.Wakeup();
spiNorFlash.Wakeup();
lcd.Wakeup();
touchPanel.Wakeup();
displayApp->PushMessage(Applications::DisplayApp::Messages::GoToRunning);
displayApp->PushMessage(Applications::DisplayApp::Messages::UpdateBatteryLevel);
}
void SystemTask::OnTouchEvent() {
if(isGoingToSleep) return ;
NRF_LOG_INFO("[SystemTask] Touch event");
if(!isSleeping) {
PushMessage(Messages::OnTouchEvent);
@ -213,6 +222,9 @@ void SystemTask::OnTouchEvent() {
}
void SystemTask::PushMessage(SystemTask::Messages msg) {
if(msg == Messages::GoToSleep) {
isGoingToSleep = true;
}
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(systemTaksMsgQueue, &msg, &xHigherPriorityTaskWoken);
@ -229,6 +241,6 @@ void SystemTask::OnIdle() {
}
void SystemTask::ReloadIdleTimer() const {
if(isSleeping) return;
if(isSleeping || isGoingToSleep) return;
xTimerReset(idleTimer, 0);
}

View File

@ -54,7 +54,9 @@ namespace Pinetime {
Pinetime::Controllers::Ble& bleController;
Pinetime::Controllers::DateTime& dateTimeController;
QueueHandle_t systemTaksMsgQueue;
bool isSleeping = false;
std::atomic<bool> isSleeping{false};
std::atomic<bool> isGoingToSleep{false};
std::atomic<bool> isWakingUp{false};
Pinetime::Drivers::Watchdog watchdog;
Pinetime::Drivers::WatchdogView watchdogView;
Pinetime::Controllers::NotificationManager& notificationManager;

View File

@ -140,9 +140,11 @@ void TwiMaster::Write(uint8_t deviceAddress, const uint8_t *data, size_t size, b
}
void TwiMaster::Sleep() {
while(twiBaseAddress->ENABLE != 0) {
twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos);
}
nrf_gpio_cfg_default(6);
nrf_gpio_cfg_default(7);
twiBaseAddress->ENABLE = 0;
NRF_LOG_INFO("[TWIMASTER] Sleep");
}