Skip to content

Commit c12dbe5

Browse files
authored
Merge branch 'main' into improve-alarm-preview
2 parents 7777af7 + 9e406c7 commit c12dbe5

13 files changed

+130
-93
lines changed

src/FreeRTOSConfig.h

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
#define configUSE_TIME_SLICING 0
7676
#define configUSE_NEWLIB_REENTRANT 0
7777
#define configENABLE_BACKWARD_COMPATIBILITY 1
78+
#define configUSE_TASK_NOTIFICATIONS 0
7879

7980
/* Hook function related definitions. */
8081
#define configUSE_IDLE_HOOK 0

src/displayapp/DisplayApp.cpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ void DisplayApp::Start(System::BootErrors error) {
125125
bootError = error;
126126

127127
lvgl.Init();
128+
motorController.Init();
128129

129130
if (error == System::BootErrors::TouchController) {
130131
LoadNewScreen(Apps::Error, DisplayApp::FullRefreshDirections::None);
@@ -142,9 +143,6 @@ void DisplayApp::Process(void* instance) {
142143
NRF_LOG_INFO("displayapp task started!");
143144
app->InitHw();
144145

145-
// Send a dummy notification to unlock the lvgl display driver for the first iteration
146-
xTaskNotifyGive(xTaskGetCurrentTaskHandle());
147-
148146
while (true) {
149147
app->Refresh();
150148
}
@@ -153,7 +151,6 @@ void DisplayApp::Process(void* instance) {
153151
void DisplayApp::InitHw() {
154152
brightnessController.Init();
155153
ApplyBrightness();
156-
motorController.Init();
157154
lcd.Init();
158155
}
159156

src/displayapp/DisplayAppRecovery.cpp

-5
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ void DisplayApp::Process(void* instance) {
3838
auto* app = static_cast<DisplayApp*>(instance);
3939
NRF_LOG_INFO("displayapp task started!");
4040

41-
// Send a dummy notification to unlock the lvgl display driver for the first iteration
42-
xTaskNotifyGive(xTaskGetCurrentTaskHandle());
43-
4441
app->InitHw();
4542
while (true) {
4643
app->Refresh();
@@ -94,7 +91,6 @@ void DisplayApp::DisplayLogo(uint16_t color) {
9491
Pinetime::Tools::RleDecoder rleDecoder(infinitime_nb, sizeof(infinitime_nb), color, colorBlack);
9592
for (int i = 0; i < displayWidth; i++) {
9693
rleDecoder.DecodeNext(displayBuffer, displayWidth * bytesPerPixel);
97-
ulTaskNotifyTake(pdTRUE, 500);
9894
lcd.DrawBuffer(0, i, displayWidth, 1, reinterpret_cast<const uint8_t*>(displayBuffer), displayWidth * bytesPerPixel);
9995
}
10096
}
@@ -103,7 +99,6 @@ void DisplayApp::DisplayOtaProgress(uint8_t percent, uint16_t color) {
10399
const uint8_t barHeight = 20;
104100
std::fill(displayBuffer, displayBuffer + (displayWidth * bytesPerPixel), color);
105101
for (int i = 0; i < barHeight; i++) {
106-
ulTaskNotifyTake(pdTRUE, 500);
107102
uint16_t barWidth = std::min(static_cast<float>(percent) * 2.4f, static_cast<float>(displayWidth));
108103
lcd.DrawBuffer(0, displayWidth - barHeight + i, barWidth, 1, reinterpret_cast<const uint8_t*>(displayBuffer), barWidth * bytesPerPixel);
109104
}

src/displayapp/LittleVgl.cpp

-5
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,6 @@ void LittleVgl::SetFullRefresh(FullRefreshDirections direction) {
152152
void LittleVgl::FlushDisplay(const lv_area_t* area, lv_color_t* color_p) {
153153
uint16_t y1, y2, width, height = 0;
154154

155-
ulTaskNotifyTake(pdTRUE, 200);
156-
// Notification is still needed (even if there is a mutex on SPI) because of the DataCommand pin
157-
// which cannot be set/clear during a transfer.
158-
159155
if ((scrollDirection == LittleVgl::FullRefreshDirections::Down) && (area->y2 == visibleNbLines - 1)) {
160156
writeOffset = ((writeOffset + totalNbLines) - visibleNbLines) % totalNbLines;
161157
} else if ((scrollDirection == FullRefreshDirections::Up) && (area->y1 == 0)) {
@@ -219,7 +215,6 @@ void LittleVgl::FlushDisplay(const lv_area_t* area, lv_color_t* color_p) {
219215

220216
if (height > 0) {
221217
lcd.DrawBuffer(area->x1, y1, width, height, reinterpret_cast<const uint8_t*>(color_p), width * height * 2);
222-
ulTaskNotifyTake(pdTRUE, 100);
223218
}
224219

225220
uint16_t pixOffset = width * height;

src/drivers/Bma421.cpp

-7
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,6 @@ Bma421::Values Bma421::Process() {
126126
uint32_t steps = 0;
127127
bma423_step_counter_output(&steps, &bma);
128128

129-
int32_t temperature;
130-
bma4_get_temperature(&temperature, BMA4_DEG, &bma);
131-
temperature = temperature / 1000;
132-
133-
uint8_t activity = 0;
134-
bma423_activity_output(&activity, &bma);
135-
136129
// X and Y axis are swapped because of the way the sensor is mounted in the PineTime
137130
return {steps, data.y, data.x, data.z};
138131
}

src/drivers/Spi.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ Spi::Spi(SpiMaster& spiMaster, uint8_t pinCsn) : spiMaster {spiMaster}, pinCsn {
99
nrf_gpio_pin_set(pinCsn);
1010
}
1111

12-
bool Spi::Write(const uint8_t* data, size_t size) {
13-
return spiMaster.Write(pinCsn, data, size);
12+
bool Spi::Write(const uint8_t* data, size_t size, const std::function<void()>& preTransactionHook) {
13+
return spiMaster.Write(pinCsn, data, size, preTransactionHook);
1414
}
1515

1616
bool Spi::Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) {

src/drivers/Spi.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22
#include <cstdint>
33
#include <cstddef>
4+
#include <functional>
45
#include "drivers/SpiMaster.h"
56

67
namespace Pinetime {
@@ -14,7 +15,7 @@ namespace Pinetime {
1415
Spi& operator=(Spi&&) = delete;
1516

1617
bool Init();
17-
bool Write(const uint8_t* data, size_t size);
18+
bool Write(const uint8_t* data, size_t size, const std::function<void()>& preTransactionHook);
1819
bool Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize);
1920
bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize);
2021
void Sleep();

src/drivers/SpiMaster.cpp

+45-40
Original file line numberDiff line numberDiff line change
@@ -94,32 +94,45 @@ bool SpiMaster::Init() {
9494
return true;
9595
}
9696

97-
void SpiMaster::SetupWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel) {
98-
// Create an event when SCK toggles.
99-
NRF_GPIOTE->CONFIG[gpiote_channel] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | (spim->PSEL.SCK << GPIOTE_CONFIG_PSEL_Pos) |
100-
(GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos);
101-
102-
// Stop the spim instance when SCK toggles.
103-
NRF_PPI->CH[ppi_channel].EEP = (uint32_t) &NRF_GPIOTE->EVENTS_IN[gpiote_channel];
104-
NRF_PPI->CH[ppi_channel].TEP = (uint32_t) &spim->TASKS_STOP;
105-
NRF_PPI->CHENSET = 1U << ppi_channel;
97+
void SpiMaster::SetupWorkaroundForErratum58() {
98+
nrfx_gpiote_pin_t pin = spiBaseAddress->PSEL.SCK;
99+
nrfx_gpiote_in_config_t gpioteCfg = {.sense = NRF_GPIOTE_POLARITY_TOGGLE,
100+
.pull = NRF_GPIO_PIN_NOPULL,
101+
.is_watcher = false,
102+
.hi_accuracy = true,
103+
.skip_gpio_setup = true};
104+
if (!workaroundActive) {
105+
// Create an event when SCK toggles.
106+
APP_ERROR_CHECK(nrfx_gpiote_in_init(pin, &gpioteCfg, NULL));
107+
nrfx_gpiote_in_event_enable(pin, false);
108+
109+
// Stop the spim instance when SCK toggles.
110+
nrf_ppi_channel_endpoint_setup(workaroundPpi, nrfx_gpiote_in_event_addr_get(pin), spiBaseAddress->TASKS_STOP);
111+
nrf_ppi_channel_enable(workaroundPpi);
112+
}
113+
106114
spiBaseAddress->EVENTS_END = 0;
107115

108116
// Disable IRQ
109-
spim->INTENCLR = (1 << 6);
110-
spim->INTENCLR = (1 << 1);
111-
spim->INTENCLR = (1 << 19);
117+
spiBaseAddress->INTENCLR = (1 << 6);
118+
spiBaseAddress->INTENCLR = (1 << 1);
119+
spiBaseAddress->INTENCLR = (1 << 19);
120+
workaroundActive = true;
112121
}
113122

114-
void SpiMaster::DisableWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel) {
115-
NRF_GPIOTE->CONFIG[gpiote_channel] = 0;
116-
NRF_PPI->CH[ppi_channel].EEP = 0;
117-
NRF_PPI->CH[ppi_channel].TEP = 0;
118-
NRF_PPI->CHENSET = ppi_channel;
123+
void SpiMaster::DisableWorkaroundForErratum58() {
124+
nrfx_gpiote_pin_t pin = spiBaseAddress->PSEL.SCK;
125+
if (workaroundActive) {
126+
nrfx_gpiote_in_uninit(pin);
127+
nrf_ppi_channel_disable(workaroundPpi);
128+
}
119129
spiBaseAddress->EVENTS_END = 0;
120-
spim->INTENSET = (1 << 6);
121-
spim->INTENSET = (1 << 1);
122-
spim->INTENSET = (1 << 19);
130+
131+
// Enable IRQ
132+
spiBaseAddress->INTENSET = (1 << 6);
133+
spiBaseAddress->INTENSET = (1 << 1);
134+
spiBaseAddress->INTENSET = (1 << 19);
135+
workaroundActive = false;
123136
}
124137

125138
void SpiMaster::OnEndEvent() {
@@ -136,17 +149,11 @@ void SpiMaster::OnEndEvent() {
136149

137150
spiBaseAddress->TASKS_START = 1;
138151
} else {
139-
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
140-
if (taskToNotify != nullptr) {
141-
vTaskNotifyGiveFromISR(taskToNotify, &xHigherPriorityTaskWoken);
142-
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
143-
}
144-
145152
nrf_gpio_pin_set(this->pinCsn);
146153
currentBufferAddr = 0;
147-
BaseType_t xHigherPriorityTaskWoken2 = pdFALSE;
148-
xSemaphoreGiveFromISR(mutex, &xHigherPriorityTaskWoken2);
149-
portYIELD_FROM_ISR(xHigherPriorityTaskWoken | xHigherPriorityTaskWoken2);
154+
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
155+
xSemaphoreGiveFromISR(mutex, &xHigherPriorityTaskWoken);
156+
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
150157
}
151158
}
152159

@@ -173,21 +180,23 @@ void SpiMaster::PrepareRx(const uint32_t bufferAddress, const size_t size) {
173180
spiBaseAddress->EVENTS_END = 0;
174181
}
175182

176-
bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size) {
183+
bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size, const std::function<void()>& preTransactionHook) {
177184
if (data == nullptr)
178185
return false;
179186
auto ok = xSemaphoreTake(mutex, portMAX_DELAY);
180187
ASSERT(ok == true);
181-
taskToNotify = xTaskGetCurrentTaskHandle();
182188

183189
this->pinCsn = pinCsn;
184190

185191
if (size == 1) {
186-
SetupWorkaroundForFtpan58(spiBaseAddress, 0, 0);
192+
SetupWorkaroundForErratum58();
187193
} else {
188-
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
194+
DisableWorkaroundForErratum58();
189195
}
190196

197+
if (preTransactionHook != nullptr) {
198+
preTransactionHook();
199+
}
191200
nrf_gpio_pin_clear(this->pinCsn);
192201

193202
currentBufferAddr = (uint32_t) data;
@@ -205,7 +214,7 @@ bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size) {
205214
nrf_gpio_pin_set(this->pinCsn);
206215
currentBufferAddr = 0;
207216

208-
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
217+
DisableWorkaroundForErratum58();
209218

210219
xSemaphoreGive(mutex);
211220
}
@@ -216,10 +225,8 @@ bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size) {
216225
bool SpiMaster::Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) {
217226
xSemaphoreTake(mutex, portMAX_DELAY);
218227

219-
taskToNotify = nullptr;
220-
221228
this->pinCsn = pinCsn;
222-
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
229+
DisableWorkaroundForErratum58();
223230
spiBaseAddress->INTENCLR = (1 << 6);
224231
spiBaseAddress->INTENCLR = (1 << 1);
225232
spiBaseAddress->INTENCLR = (1 << 19);
@@ -265,10 +272,8 @@ void SpiMaster::Wakeup() {
265272
bool SpiMaster::WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize) {
266273
xSemaphoreTake(mutex, portMAX_DELAY);
267274

268-
taskToNotify = nullptr;
269-
270275
this->pinCsn = pinCsn;
271-
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
276+
DisableWorkaroundForErratum58();
272277
spiBaseAddress->INTENCLR = (1 << 6);
273278
spiBaseAddress->INTENCLR = (1 << 1);
274279
spiBaseAddress->INTENCLR = (1 << 19);

src/drivers/SpiMaster.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
#pragma once
22
#include <cstddef>
33
#include <cstdint>
4+
#include <functional>
45

56
#include <FreeRTOS.h>
67
#include <semphr.h>
78
#include <task.h>
9+
#include "nrfx_gpiote.h"
10+
#include "nrf_ppi.h"
811

912
namespace Pinetime {
1013
namespace Drivers {
@@ -31,7 +34,7 @@ namespace Pinetime {
3134
SpiMaster& operator=(SpiMaster&&) = delete;
3235

3336
bool Init();
34-
bool Write(uint8_t pinCsn, const uint8_t* data, size_t size);
37+
bool Write(uint8_t pinCsn, const uint8_t* data, size_t size, const std::function<void()>& preTransactionHook);
3538
bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize);
3639

3740
bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize);
@@ -43,8 +46,8 @@ namespace Pinetime {
4346
void Wakeup();
4447

4548
private:
46-
void SetupWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel);
47-
void DisableWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel);
49+
void SetupWorkaroundForErratum58();
50+
void DisableWorkaroundForErratum58();
4851
void PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size);
4952
void PrepareRx(const volatile uint32_t bufferAddress, const volatile size_t size);
5053

@@ -56,8 +59,9 @@ namespace Pinetime {
5659

5760
volatile uint32_t currentBufferAddr = 0;
5861
volatile size_t currentBufferSize = 0;
59-
volatile TaskHandle_t taskToNotify;
6062
SemaphoreHandle_t mutex = nullptr;
63+
static constexpr nrf_ppi_channel_t workaroundPpi = NRF_PPI_CHANNEL0;
64+
bool workaroundActive = false;
6165
};
6266
}
6367
}

src/drivers/SpiNorFlash.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ void SpiNorFlash::Uninit() {
2222

2323
void SpiNorFlash::Sleep() {
2424
auto cmd = static_cast<uint8_t>(Commands::DeepPowerDown);
25-
spi.Write(&cmd, sizeof(uint8_t));
25+
spi.Write(&cmd, sizeof(uint8_t), nullptr);
2626
NRF_LOG_INFO("[SpiNorFlash] Sleep")
2727
}
2828

0 commit comments

Comments
 (0)