-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
drivers/hd44780: fix potential hardfault during initialization #12634
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running on the CI to be sure but it seems to fix the failure that murdock found.
drivers/hd44780/hd44780.c
Outdated
if (dev->p.data[i] != GPIO_UNDEF) { | ||
++count_pins; | ||
} | ||
dev->data[i] = dev->p.data[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason no memcpy(dev->data, dev.p.data, ARRAY_SIZE((dev->data));
(I don't know if that is the proper array size macro but you get the idea)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried memcpy and noticed a bigger code size on ROM, that's why I kept the for loop version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, lets me run it through the test.
Hm, I'd like to understand where this bug comes from before working around it - it works in GCC and I don't see anything obviously wrong with it. After all How did you set up the |
While working on it, I discovered that saml21 based boards are broken with GCC, same for Arduino-Zero (samd21). So there's something wrong with sam0 boards in general, it's just that samr21 is less affected I would say. On the other architectures I tested (STM32, nRF51) the test is working.
Just installed llvm locally but you can also use this toolchain from within docker. |
I can't even build with
When I use |
I had the same issue with nrf52. Maybe the toolchain just doesn't support M4 ? |
A few boards have failed though I don't know if we should expect failures for this test since the boards don't have the driver connected... Maybe some GPIO pins are not valid in the boards or something: ek-lm4f120xl
stm32f3discovery - I think just a uart problem though
esp32-wroom32
|
I can build the same54-xpro with llvm:
|
@MrKevinWeiss are the failing boards also failing on master (and eventually the latest release version) ? |
Probably good to point that out... Yup failing in master too so maybe we don't worry about it, yet. |
For the same54 I seem to have some flashing problems, looking into it.
|
Bumped the version of edbg and cleared out the binary in
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this is a bugfix and it only affects the driver I think it should be in sooner than later. I tested and it fixes the bugs and does not introduce any new ones. I will ACK, @benpicco @kaspar030 if you have any objections now it the time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
diff --git a/drivers/hd44780/hd44780.c b/drivers/hd44780/hd44780.c
index 73b2a6072..26b0ec341 100644
--- a/drivers/hd44780/hd44780.c
+++ b/drivers/hd44780/hd44780.c
@@ -110,20 +110,16 @@ int hd44780_init(hd44780_t *dev, const hd44780_params_t *params)
LOG_ERROR("hd44780_init: invalid LCD size!\n");
return -1;
}
- uint8_t count_pins = 0;
- /* check which pins are used */
- for (unsigned i = 0; i < HD44780_MAX_PINS; ++i) {
- if (dev->p.data[i] != GPIO_UNDEF) {
- ++count_pins;
- }
- }
- /* set mode depending on configured pins */
- if (count_pins < HD44780_MAX_PINS) {
- dev->flag |= HD44780_4BITMODE;
+
+ /* set mode depending on configured pins:
+ if 4th pin is set, use 8bit mode, else use 4bit mode*/
+ if (dev->p.data[4] != GPIO_UNDEF) {
+ dev->flag |= HD44780_8BITMODE;
}
else {
- dev->flag |= HD44780_8BITMODE;
+ dev->flag |= HD44780_4BITMODE;
}
+
/* set flag for 1 or 2 row mode, 4 rows are 2 rows split half */
if (dev->p.rows > 1) {
dev->flag |= HD44780_2LINE;
This part of the patch is enough to fix the bug.
oops, no - the TOOLCHAIN=llvm
slipped though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually the patch is much simpler:
diff --git a/drivers/hd44780/hd44780.c b/drivers/hd44780/hd44780.c
index 73b2a6072..8bdb83c40 100644
--- a/drivers/hd44780/hd44780.c
+++ b/drivers/hd44780/hd44780.c
@@ -117,6 +117,8 @@ int hd44780_init(hd44780_t *dev, const hd44780_params_t *params)
++count_pins;
}
}
+
+ dev->flag = 0;
/* set mode depending on configured pins */
if (count_pins < HD44780_MAX_PINS) {
dev->flag |= HD44780_4BITMODE;
flags
is uninitialized so the HD44780_8BITMODE
is erroneously set.
And since sam0
stores the address of the GPIO port inside gpio_t
, calling gpio_set(-1)
does not fare well.
And HD44780_4BITMODE
is never used, only set - I'd suggest to remove it so we can't set HD44780_4BITMODE
and HD44780_8BITMODE
at the same time - an unset HD44780_8BITMODE
should indicate 4 Bit mode.
Thanks @benpicco! That was it. Good catch! |
Another solution is to declare the device descriptor static in the test application. |
Co-authored-by Benjamin Valentin <benpicco@googlemail.com>
0c18788
to
c7fac09
Compare
I agree this is not nice. But it is showing the potential initialization difference between structures initialized on the stack and structures defined statically. |
I reworked the PR with the simple fix proposed by @benpicco. AFAICT, everything works locally with this patch. |
I still liked the change to just check if the 4th pin is set instead of counting the pins. |
Indeed. And it was saving some memory on ROM. I'll push a commit for this. |
The driver can only be used with either 4 or 8 bit modes. Checking if the 5th pin is set in the configuration is enough the determine if 8bit mode should be used or not
Done. With this we save 16B on ROM for Arduino-Zero, not that much but better than before. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this the driver doesn't crash anymore on samr21 when build with LLVM.
This reverts commit cf01c74. Adding an unexplained delay seemed wrong in the first place, but it fixed the display on the MCB2388. Turns out the display was erroneously operating in 8-bit mode due to the uninitialized flag register. Why the delay helped here I don't know. But with RIOT-OS#12634 fixing this, this hack is not needed anymore.
This reverts commit cf01c74. Adding an unexplained delay seemed wrong in the first place, but it fixed the display on the MCB2388. Turns out the display was erroneously operating in 8-bit mode due to the uninitialized flag register. Why the delay helped here I don't know. But with RIOT-OS#12634 fixing this, this hack is not needed anymore.
Contribution description
This PR fixes a hardfault when running the
tests/driver_hd44780
application on samr21-xpro, when built with LLVM, as reported in #12487 (comment).In fact, the test application also crashes when run on arduino-zero/samr30-xpro if built GCC or LLVM.
Since the data pins array param is stored on flash memory and the driver is accessing it in loops for initializing/setting/clearing the pins. I thought that there was something with this that could cause a crash so this PR is just adding a extra array in RAM for and use it in the driver instead of the param array. It seems to work, at least it doesn't crash anymore.
Surprisingly, there's no RAM increase, just 24 extra bytes on ROM.
There might be something else, related to SAM0 platforms since it works well on the other platforms I tested (STM32, nRF), but I have no idea what it could be.
Testing procedure
Changing BOARD for arduino-zero or samr30-xpro none of the 2 commands works on master but both are fixed by this PR.
Issues/PRs references
Fixes the issue reported in #12487 (comment)