Hi all,
I started to play with i.MX93 FRDM board and when I wrote a simple script to control RGB LEDs on the board, I've managed to control only Green and Blue LEDs. Red LED stays ON whatever I tried.
Based on the schematics, all leds are connected in a similar manner, so they operate Active High.
Here is my script:
---------------------------
#!/bin/sh
PERIOD=1000000
set_pwm() {
CHIP=$1
CHANNEL=$2
DUTY=$3
PWM_PATH="/sys/class/pwm/pwmchip${CHIP}/pwm${CHANNEL}"
if [ ! -d "$PWM_PATH" ]; then
echo "$CHANNEL" > "/sys/class/pwm/pwmchip${CHIP}/export" 2>/dev/null
fi
# Reset duty cycle to 0 first to satisfy TPM driver constraints
echo 0 > "${PWM_PATH}/duty_cycle" 2>/dev/null
echo "$PERIOD" > "${PWM_PATH}/period"
echo "$DUTY" > "${PWM_PATH}/duty_cycle"
echo 1 > "${PWM_PATH}/enable" 2>/dev/null
}
# Red is Active-Low: Default OFF = 1000000 (3.3V / High)
RED_DUTY=${1:-0}
# Green and Blue are Active-High: Default OFF = 0 (0V / Low)
GREEN_DUTY=${2:-0}
BLUE_DUTY=${3:-0}
# Red -> pwmchip4, Channel 3
set_pwm 4 3 "$RED_DUTY"
# Green -> pwmchip0, Channel 0
set_pwm 0 0 "$GREEN_DUTY"
# Blue -> pwmchip0, Channel 2
set_pwm 0 2 "$BLUE_DUTY"
-------------------------------------------
I've checked that red LED (GPIO_IO13) is allocated to the ledsgrp2:
pin 17 (IMX93_IOMUXC_GPIO_IO13): 424f0000.pwm (GPIO UNCLAIMED) function pinctrl group ledsgrp2
as far as I can see with debugfs commands, the pin GPIO_IO13 is configured for ALT1 mode, which is a TPM2 channel 3 (PWM).
when I run the script, I can successfully control Blue and Green LEDS but Red LED stays ON.
Is there something that I miss?
Hi @ilya_chepurin
The RED LED is channel 2, please use below script to test(verified on L6.18.20)
#!/bin/sh
# RGB LED PWM cycle test for i.MX93 EVK/FRDM.
# Sequence per cycle: RED on 1s -> all off 1s -> GREEN on 1s -> all off 1s -> BLUE on 1s -> all off 1s
# Usage: ./run.sh [LOOPS] LOOPS: number of full cycles, 0 = infinite, default 3
# Timing overridable via env: ON_TIME=2 REST_TIME=1 ./run.sh
PERIOD=1000000 # 1 kHz period in ns
ON_TIME=${ON_TIME:-1} # seconds a color stays ON
REST_TIME=${REST_TIME:-1} # seconds all OFF between colors
LOOPS=${1:-3}
RETRIES=50
# Channel mapping and polarity (verified on this board, all ACTIVE-HIGH):
# Red -> 424f0000.pwm = pwmchip1 ch2 ON=duty PERIOD OFF=duty 0
# Green -> 424e0000.pwm = pwmchip0 ch0 ON=duty PERIOD OFF=duty 0
# Blue -> 424e0000.pwm = pwmchip0 ch2 ON=duty PERIOD OFF=duty 0
RED_CHIP=1; RED_CH=2
GRN_CHIP=0; GRN_CH=0
BLU_CHIP=0; BLU_CH=2
# write_retry FILE VALUE : write VALUE to FILE, retry on transient TPM busy/-ETIME,
# and confirm the value took effect. Returns 0 on success.
write_retry() {
t=0
while [ "$t" -lt "$RETRIES" ]; do
echo "$2" > "$1" 2>/dev/null
[ "$(cat "$1" 2>/dev/null)" = "$2" ] && return 0
t=$((t+1))
done
echo "WARN: could not write $2 to $1" >&2
return 1
}
# init_pwm CHIP CH : export (fresh), set period BEFORE duty, start disabled with duty 0.
# The i.MX TPM shares a counter between channels; a stale export with period=0 makes
# later period writes fail with -EBUSY, so we unexport first for a clean state.
init_pwm() {
P="/sys/class/pwm/pwmchip${1}"
[ -d "${P}/pwm${2}" ] && echo "$2" > "${P}/unexport" 2>/dev/null
echo "$2" > "${P}/export" 2>/dev/null
write_retry "${P}/pwm${2}/period" "$PERIOD" # period must be set before duty
write_retry "${P}/pwm${2}/duty_cycle" 0 # start OFF
echo 1 > "${P}/pwm${2}/enable" 2>/dev/null
}
set_duty() { # CHIP CH DUTY
write_retry "/sys/class/pwm/pwmchip${1}/pwm${2}/duty_cycle" "$3"
}
led() { # CHIP CH STATE(on|off) -- all channels active-high
if [ "$3" = on ]; then set_duty "$1" "$2" "$PERIOD"; else set_duty "$1" "$2" 0; fi
}
all_off() {
led $RED_CHIP $RED_CH off
led $GRN_CHIP $GRN_CH off
led $BLU_CHIP $BLU_CH off
}
# Init: green and blue share pwmchip0, so init green first, then blue.
init_pwm $RED_CHIP $RED_CH
init_pwm $GRN_CHIP $GRN_CH
init_pwm $BLU_CHIP $BLU_CH
trap "all_off; echo; echo interrupted, all LEDs off; exit 0" INT TERM
all_off
echo "start: all OFF"
n=0
while :; do
c=$((n+1))
echo "[cycle $c] RED on"; led $RED_CHIP $RED_CH on; sleep "$ON_TIME"
echo "[cycle $c] --- off"; all_off; sleep "$REST_TIME"
echo "[cycle $c] GREEN on"; led $GRN_CHIP $GRN_CH on; sleep "$ON_TIME"
echo "[cycle $c] --- off"; all_off; sleep "$REST_TIME"
echo "[cycle $c] BLUE on"; led $BLU_CHIP $BLU_CH on; sleep "$ON_TIME"
echo "[cycle $c] --- off"; all_off; sleep "$REST_TIME"
n=$c
[ "$LOOPS" -eq 0 ] && continue
[ "$n" -ge "$LOOPS" ] && break
done
all_off
echo "done ($n cycle(s)), all LEDs off"
Best Regards,
Zhiming