-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LED: Fix artefacts. #61
Conversation
Basic idea to change the state of the Pins: 1) Tri-State all (will TURN OFF all LEDs) 2) Define correct High/Low value for Pins 3) Drive pins which need driving (will TURN ON correct LEDs)
Reviewer's Guide by SourceryThis pull request fixes LED artefacts by changing how the GPIO pins are controlled. It first sets all pins to a tri-state (off) mode, then sets the desired high/low values for each pin, and finally drives only the pins that need to be turned on. This ensures that only the correct LEDs are illuminated and prevents unintended LED behavior. Sequence diagram for GPIO pin control flowsequenceDiagram
participant GPIO as GPIO Controller
participant DIR as Direction Register
participant OUT as Output Register
participant DRV as Drive Strength Register
GPIO->>DIR: Clear all pin directions (tri-state)
GPIO->>OUT: Set output values
alt Drive strength is 20mA
GPIO->>DRV: Update drive strength
end
GPIO->>DIR: Enable selected pin directions
Class diagram for LED driver structureclassDiagram
class pinctrl_t {
+uint8_t* cfg_buf
+uint8_t* port_buf
+uint32_t pin
}
class GPIO_Constants {
+GPIO_PD_DRV
+GPIO_DIR
+GPIO_OUT
}
class LED_Driver {
-pinctrl_t led_pins[]
-uint32_t drive_strength
+led_setDriveStrength(is_20mA)
-gpio_buf_apply()
-gpio_buf_set()
}
LED_Driver --> pinctrl_t
LED_Driver --> GPIO_Constants
State diagram for LED pin control sequencestateDiagram-v2
[*] --> AllPinsTriState: 1. Turn off all LEDs
AllPinsTriState --> SetPinValues: 2. Set High/Low values
SetPinValues --> DrivePins: 3. Drive selected pins
DrivePins --> [*]: LEDs in correct state
note right of AllPinsTriState: All pins floating
note right of SetPinValues: Configure output values
note right of DrivePins: Enable only needed pins
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
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.
Hey @lundril - I've reviewed your changes and they look great!
Here's what I looked at during the review
- 🟢 General issues: all looks good
- 🟡 Security: 1 issue found
- 🟢 Testing: all looks good
- 🟡 Complexity: 1 issue found
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
src/leddrv.c
Outdated
dir_val = (dir_val & ~*mask); // first turn off drive to all Pins | ||
|
||
uint32_t *out = (uint32_t *)(gpio_base + GPIO_OUT); | ||
*out = (*out & ~*mask) | (*port & *mask); | ||
*dir = dir_val; | ||
*out = out_val; | ||
if (drive_strength) { | ||
*drv = drv_val; | ||
} | ||
dir_val = dir_val | (*cfg & *mask); // now turn on drive to right Pins |
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.
🚨 suggestion (security): Consider protecting the break-before-make sequence from interrupts
While the break-before-make sequence prevents shoot-through current, interrupts between the two dir register updates could cause temporary pin state issues. Consider using critical sections if this is a concern in your system.
Suggested implementation:
#include <stdint.h>
#include <zephyr/irq.h>
unsigned int key = irq_lock();
dir_val = (dir_val & ~*mask); // first turn off drive to all Pins
*dir = dir_val;
*out = out_val;
if (drive_strength) {
*drv = drv_val;
}
dir_val = dir_val | (*cfg & *mask); // now turn on drive to right Pins
*dir = dir_val;
irq_unlock(key);
Note: This assumes the code is running on Zephyr RTOS. If using a different RTOS or bare metal, you'll need to use the appropriate critical section / interrupt disable functions for your system.
src/leddrv.c
Outdated
@@ -36,19 +36,33 @@ void led_setDriveStrength(int is_20mA) | |||
} | |||
|
|||
static void gpio_buf_apply( |
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.
issue (complexity): Consider restructuring gpio_buf_apply to clarify the hardware-driven timing sequence by grouping register access, using const for safety, and adding explanatory comments.
The gpio_buf_apply function's complexity appears driven by hardware timing requirements, but needs better documentation and structure. Consider:
static void gpio_buf_apply(
volatile uint8_t *gpio_base,
uint32_t *port, uint32_t *cfg,
uint32_t *mask)
{
// Define register pointers
volatile uint32_t * const drv = (volatile uint32_t *)(gpio_base + GPIO_PD_DRV);
volatile uint32_t * const dir = (volatile uint32_t *)(gpio_base + GPIO_DIR);
volatile uint32_t * const out = (volatile uint32_t *)(gpio_base + GPIO_OUT);
// Read current register values
const uint32_t drv_val = drive_strength ? *drv : 0;
const uint32_t dir_val = *dir;
const uint32_t out_val = *out;
// Prepare new values
const uint32_t new_drv = (drv_val & ~*mask) | (*cfg & *mask);
const uint32_t new_out = (out_val & ~*mask) | (*port & *mask);
// Hardware timing sequence:
// 1. Disable all affected pins
*dir = dir_val & ~*mask;
// 2. Update output and drive strength while pins are disabled
*out = new_out;
if (drive_strength) {
*drv = new_drv;
}
// 3. Enable affected pins with new configuration
*dir = (dir_val & ~*mask) | (*cfg & *mask);
}
This restructuring:
- Groups register access into clear phases
- Uses const to prevent accidental modifications
- Adds comments explaining the timing sequence
- Makes the hardware requirements more obvious through code structure
Fix artefacts when using high brightness. Highter drive strength if more than 5 LEDs need to be turned on.
Wow. Now I see what caused these artefacts. It was a real headache for me. |
Basic idea to change the state of the Pins:
Summary by Sourcery
Bug Fixes: