Merge branch 'twimaster_rework' of https://github.com/Riksu9000/InfiniTime into Riksu9000-twimaster_rework

# Conflicts:
#	src/systemtask/SystemTask.cpp
This commit is contained in:
Jean-François Milants 2021-08-28 15:08:50 +02:00
commit 45e7638fc2
4 changed files with 49 additions and 88 deletions

View file

@ -8,45 +8,39 @@ using namespace Pinetime::Drivers;
// TODO use shortcut to automatically send STOP when receive LastTX, for example // TODO use shortcut to automatically send STOP when receive LastTX, for example
// TODO use DMA/IRQ // TODO use DMA/IRQ
TwiMaster::TwiMaster(const Modules module, const Parameters& params) : module {module}, params {params} { TwiMaster::TwiMaster(NRF_TWIM_Type* module, uint32_t frequency, uint8_t pinSda, uint8_t pinScl)
: module {module}, frequency {frequency}, pinSda {pinSda}, pinScl {pinScl} {
}
void TwiMaster::ConfigurePins() const {
NRF_GPIO->PIN_CNF[pinScl] =
(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
(GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
(GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
NRF_GPIO->PIN_CNF[pinSda] =
(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
(GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
(GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
} }
void TwiMaster::Init() { void TwiMaster::Init() {
if(mutex == nullptr) if (mutex == nullptr) {
mutex = xSemaphoreCreateBinary(); mutex = xSemaphoreCreateBinary();
NRF_GPIO->PIN_CNF[params.pinScl] =
((uint32_t) GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | ((uint32_t) GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
((uint32_t) GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | ((uint32_t) GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
((uint32_t) GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
NRF_GPIO->PIN_CNF[params.pinSda] =
((uint32_t) GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | ((uint32_t) GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
((uint32_t) GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | ((uint32_t) GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
((uint32_t) GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
switch (module) {
case Modules::TWIM1:
twiBaseAddress = NRF_TWIM1;
break;
default:
return;
} }
switch (static_cast<Frequencies>(params.frequency)) { ConfigurePins();
case Frequencies::Khz100:
twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K100;
break;
case Frequencies::Khz250:
twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K250;
break;
case Frequencies::Khz400:
twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K400;
break;
}
twiBaseAddress->PSEL.SCL = params.pinScl; twiBaseAddress = module;
twiBaseAddress->PSEL.SDA = params.pinSda;
twiBaseAddress->FREQUENCY = frequency;
twiBaseAddress->PSEL.SCL = pinScl;
twiBaseAddress->PSEL.SDA = pinSda;
twiBaseAddress->EVENTS_LASTRX = 0; twiBaseAddress->EVENTS_LASTRX = 0;
twiBaseAddress->EVENTS_STOPPED = 0; twiBaseAddress->EVENTS_STOPPED = 0;
twiBaseAddress->EVENTS_LASTTX = 0; twiBaseAddress->EVENTS_LASTTX = 0;
@ -57,19 +51,15 @@ void TwiMaster::Init() {
twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos); twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos);
/* // IRQ
NVIC_ClearPendingIRQ(_IRQn);
NVIC_SetPriority(_IRQn, 2);
NVIC_EnableIRQ(_IRQn);
*/
xSemaphoreGive(mutex); xSemaphoreGive(mutex);
} }
TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* data, size_t size) { TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* data, size_t size) {
xSemaphoreTake(mutex, portMAX_DELAY); xSemaphoreTake(mutex, portMAX_DELAY);
Wakeup();
auto ret = Write(deviceAddress, &registerAddress, 1, false); auto ret = Write(deviceAddress, &registerAddress, 1, false);
ret = Read(deviceAddress, data, size, true); ret = Read(deviceAddress, data, size, true);
Sleep();
xSemaphoreGive(mutex); xSemaphoreGive(mutex);
return ret; return ret;
} }
@ -77,9 +67,11 @@ TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAdd
TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size) { TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size) {
ASSERT(size <= maxDataSize); ASSERT(size <= maxDataSize);
xSemaphoreTake(mutex, portMAX_DELAY); xSemaphoreTake(mutex, portMAX_DELAY);
Wakeup();
internalBuffer[0] = registerAddress; internalBuffer[0] = registerAddress;
std::memcpy(internalBuffer + 1, data, size); std::memcpy(internalBuffer + 1, data, size);
auto ret = Write(deviceAddress, internalBuffer, size + 1, true); auto ret = Write(deviceAddress, internalBuffer, size + 1, true);
Sleep();
xSemaphoreGive(mutex); xSemaphoreGive(mutex);
return ret; return ret;
} }
@ -170,17 +162,11 @@ TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, const uint8_t* dat
} }
void TwiMaster::Sleep() { void TwiMaster::Sleep() {
while (twiBaseAddress->ENABLE != 0) { twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos);
twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos);
}
nrf_gpio_cfg_default(6);
nrf_gpio_cfg_default(7);
NRF_LOG_INFO("[TWIMASTER] Sleep");
} }
void TwiMaster::Wakeup() { void TwiMaster::Wakeup() {
Init(); twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos);
NRF_LOG_INFO("[TWIMASTER] Wakeup");
} }
/* Sometimes, the TWIM device just freeze and never set the event EVENTS_LASTTX. /* Sometimes, the TWIM device just freeze and never set the event EVENTS_LASTTX.
@ -190,20 +176,10 @@ void TwiMaster::Wakeup() {
* */ * */
void TwiMaster::FixHwFreezed() { void TwiMaster::FixHwFreezed() {
NRF_LOG_INFO("I2C device frozen, reinitializing it!"); NRF_LOG_INFO("I2C device frozen, reinitializing it!");
// Disable I²C
uint32_t twi_state = NRF_TWI1->ENABLE; uint32_t twi_state = NRF_TWI1->ENABLE;
twiBaseAddress->ENABLE = TWIM_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
NRF_GPIO->PIN_CNF[params.pinScl] = Sleep();
((uint32_t) GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | ((uint32_t) GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
((uint32_t) GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | ((uint32_t) GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
((uint32_t) GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
NRF_GPIO->PIN_CNF[params.pinSda] =
((uint32_t) GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | ((uint32_t) GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
((uint32_t) GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | ((uint32_t) GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
((uint32_t) GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
// Re-enable I²C
twiBaseAddress->ENABLE = twi_state; twiBaseAddress->ENABLE = twi_state;
} }

View file

@ -8,16 +8,9 @@ namespace Pinetime {
namespace Drivers { namespace Drivers {
class TwiMaster { class TwiMaster {
public: public:
enum class Modules { TWIM1 };
enum class Frequencies { Khz100, Khz250, Khz400 };
enum class ErrorCodes { NoError, TransactionFailed }; enum class ErrorCodes { NoError, TransactionFailed };
struct Parameters {
uint32_t frequency;
uint8_t pinSda;
uint8_t pinScl;
};
TwiMaster(const Modules module, const Parameters& params); TwiMaster(NRF_TWIM_Type* module, uint32_t frequency, uint8_t pinSda, uint8_t pinScl);
void Init(); void Init();
ErrorCodes Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size); ErrorCodes Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size);
@ -30,10 +23,14 @@ namespace Pinetime {
ErrorCodes Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop); ErrorCodes Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop);
ErrorCodes Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop); ErrorCodes Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop);
void FixHwFreezed(); void FixHwFreezed();
void ConfigurePins() const;
NRF_TWIM_Type* twiBaseAddress; NRF_TWIM_Type* twiBaseAddress;
SemaphoreHandle_t mutex = nullptr; SemaphoreHandle_t mutex = nullptr;
const Modules module; NRF_TWIM_Type* module;
const Parameters params; uint32_t frequency;
uint8_t pinSda;
uint8_t pinScl;
static constexpr uint8_t maxDataSize {16}; static constexpr uint8_t maxDataSize {16};
static constexpr uint8_t registerSize {1}; static constexpr uint8_t registerSize {1};
uint8_t internalBuffer[maxDataSize + registerSize]; uint8_t internalBuffer[maxDataSize + registerSize];
@ -41,4 +38,4 @@ namespace Pinetime {
static constexpr uint32_t HwFreezedDelay {161000}; static constexpr uint32_t HwFreezedDelay {161000};
}; };
} }
} }

View file

@ -84,8 +84,7 @@ Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi};
// respecting correct timings. According to erratas heet, this magic value makes it run // respecting correct timings. According to erratas heet, this magic value makes it run
// at ~390Khz with correct timings. // at ~390Khz with correct timings.
static constexpr uint32_t MaxTwiFrequencyWithoutHardwareBug {0x06200000}; static constexpr uint32_t MaxTwiFrequencyWithoutHardwareBug {0x06200000};
Pinetime::Drivers::TwiMaster twiMaster {Pinetime::Drivers::TwiMaster::Modules::TWIM1, Pinetime::Drivers::TwiMaster twiMaster {NRF_TWIM1, MaxTwiFrequencyWithoutHardwareBug, pinTwiSda, pinTwiScl};
Pinetime::Drivers::TwiMaster::Parameters {MaxTwiFrequencyWithoutHardwareBug, pinTwiSda, pinTwiScl}};
Pinetime::Drivers::Cst816S touchPanel {twiMaster, touchPanelTwiAddress}; Pinetime::Drivers::Cst816S touchPanel {twiMaster, touchPanelTwiAddress};
#ifdef PINETIME_IS_RECOVERY #ifdef PINETIME_IS_RECOVERY
static constexpr bool isFactory = true; static constexpr bool isFactory = true;

View file

@ -220,7 +220,6 @@ void SystemTask::Work() {
break; break;
case Messages::GoToRunning: case Messages::GoToRunning:
spi.Wakeup(); spi.Wakeup();
twiMaster.Wakeup();
// Double Tap needs the touch screen to be in normal mode // Double Tap needs the touch screen to be in normal mode
if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
@ -241,16 +240,12 @@ void SystemTask::Work() {
isDimmed = false; isDimmed = false;
break; break;
case Messages::TouchWakeUp: { case Messages::TouchWakeUp: {
twiMaster.Wakeup(); auto touchInfo = touchPanel.GetTouchInfo();
touchHandler.GetNewTouchInfo(); if (touchInfo.isTouch and ((touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and
auto gesture = touchHandler.GestureGet(); settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) or
if ((gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap && (touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap and
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) || settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
(gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap &&
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap))) {
GoToRunning(); GoToRunning();
} else {
twiMaster.Sleep();
} }
} break; } break;
case Messages::GoToSleep: case Messages::GoToSleep:
@ -320,7 +315,6 @@ void SystemTask::Work() {
if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
touchPanel.Sleep(); touchPanel.Sleep();
} }
twiMaster.Sleep();
isSleeping = true; isSleeping = true;
isGoingToSleep = false; isGoingToSleep = false;
@ -372,17 +366,12 @@ void SystemTask::UpdateMotion() {
if (isSleeping && !settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)) if (isSleeping && !settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist))
return; return;
if (isSleeping)
twiMaster.Wakeup();
if (stepCounterMustBeReset) { if (stepCounterMustBeReset) {
motionSensor.ResetStepCounter(); motionSensor.ResetStepCounter();
stepCounterMustBeReset = false; stepCounterMustBeReset = false;
} }
auto motionValues = motionSensor.Process(); auto motionValues = motionSensor.Process();
if (isSleeping)
twiMaster.Sleep();
motionController.IsSensorOk(motionSensor.IsOk()); motionController.IsSensorOk(motionSensor.IsOk());
motionController.Update(motionValues.x, motionValues.y, motionValues.z, motionValues.steps); motionController.Update(motionValues.x, motionValues.y, motionValues.z, motionValues.steps);