TS-7250-V3 FPGA PWM: Difference between revisions
No edit summary |
No edit summary |
||
(9 intermediate revisions by the same user not shown) | |||
Line 21: | Line 21: | ||
|- | |- | ||
| /sys/class/pwm/pwmchip0/pwm0/polarity | | /sys/class/pwm/pwmchip0/pwm0/polarity | ||
| When "normal", idle high and duty cycle low. When "inversed", idle low and duty cycle high. | | When "normal", idle high and duty cycle low. When "inversed", idle low and duty cycle high. A valid period must be set before this can be changed. | ||
|} | |} | ||
For example, for a 50hz signal with 25% duty cycle: | For example, for a 50hz signal with 25% duty cycle: | ||
Line 36: | Line 36: | ||
</source> | </source> | ||
The Linux PWM API will attempt to arrive at the exact period at the cost of the duty cycle resolution. For the most | The Linux PWM API will attempt to arrive at the exact period at the cost of the duty cycle resolution. For the most possible duty cycle resolution use one of the max period ns values from the table below. | ||
<!-- | <!-- | ||
Line 45: | Line 45: | ||
--> | --> | ||
{|class=wikitable | {|class=wikitable | ||
! | ! Shift | ||
! PWM Input Frequency (hz) | ! PWM Input Frequency (hz) | ||
! Max Period (ns) | ! Max Period (ns) | ||
Line 56: | Line 56: | ||
|- | |- | ||
| 1 | | 1 | ||
| | | 39600000 | ||
| 25833 | | 25833 | ||
| 38710 | | 38710 | ||
|- | |- | ||
| 2 | | 2 | ||
| | | 19800000 | ||
| 51667 | | 51667 | ||
| 19355 | | 19355 | ||
|- | |- | ||
| 3 | | 3 | ||
| | | 9900000 | ||
| 103333 | | 103333 | ||
| 9677 | | 9677 | ||
|- | |- | ||
| 4 | | 4 | ||
| | | 4950000 | ||
| 206667 | | 206667 | ||
| 4839 | | 4839 | ||
|- | |- | ||
| 5 | | 5 | ||
| | | 2475000 | ||
| 413333 | | 413333 | ||
| 2419 | | 2419 | ||
|- | |- | ||
| 6 | | 6 | ||
| | | 1237500 | ||
| 826667 | | 826667 | ||
| 1210 | | 1210 | ||
|- | |- | ||
| 7 | | 7 | ||
| | | 618750 | ||
| 1653333 | | 1653333 | ||
| 605 | | 605 | ||
|- | |- | ||
| 8 | | 8 | ||
| | | 309375 | ||
| 3306667 | | 3306667 | ||
| 302 | | 302 | ||
|- | |- | ||
| 9 | | 9 | ||
| | | 154687 | ||
| 6613333 | | 6613333 | ||
| 151 | | 151 | ||
|- | |- | ||
| 10 | | 10 | ||
| | | 77343 | ||
| 13226795 | | 13226795 | ||
| 76 | | 76 | ||
|- | |- | ||
| 11 | | 11 | ||
| | | 38671 | ||
| 26453932 | | 26453932 | ||
| 38 | | 38 | ||
Line 116: | Line 116: | ||
</source> | </source> | ||
If this is enabled, after setting a frequency: | If this is enabled, the kernel can output additional information after setting a frequency: | ||
<source lang=bash> | <source lang=bash> | ||
echo 0 > /sys/class/pwm/pwmchip0/export | echo 0 > /sys/class/pwm/pwmchip0/export | ||
#10ms period: | # 10ms period: | ||
echo 10000000 > /sys/class/pwm/pwmchip0/pwm0/period | echo 10000000 > /sys/class/pwm/pwmchip0/pwm0/period | ||
# 5ms duty cycle: | |||
echo 5000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle | echo 5000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle | ||
echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable | echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable | ||
Line 132: | Line 133: | ||
</console> | </console> | ||
The last value in cnt indicates how much resolution is available for the duty cycle at this given period. | The last value in cnt indicates how much resolution is available for the duty cycle at this given period. In the best case there are 10 bits (0-2047) to specify duty cycle, but this above example is 0-773 to arrive at this particular period. You can determine the duty cycle increments with period / cnt. From the above example: | ||
10000000 / 773 = 12936.61 | 10000000 / 773 = 12936.61 | ||
The duty cycle can then be configured in increments of 12936ns. | |||
The duty cycle can then be configured in increments of 12936ns. Smaller values will round to the closest value. | |||
This PWM will allow a max speed of 79.2MHz / 3 = 26.4MHz, but this will sacrifice all of the available duty cycle except an on/50%/off. The slowest speed is highest divisor at 38hz. | |||
While the Linux driver is recommended for most users, the PWM core is located at 0x500001a8. | While the Linux driver is recommended for most users, the PWM core is located at 0x500001a8. | ||
Line 168: | Line 173: | ||
|- | |- | ||
| rowspan=2 | 0x6 | | rowspan=2 | 0x6 | ||
| 15: | | 15:4 | ||
| Reserved | | Reserved | ||
|- | |- | ||
| | | 3:0 | ||
| shift (Clock frequency = 79200000 / (1 >> shift)) | | shift (Clock frequency = 79200000 / (1 >> shift)) | ||
|} | |} |
Latest revision as of 16:06, 9 April 2024
The TS-7250-V3 includes a PWM core that supports 10-bit duty/period, a 79.2mhz input clock, and 12 values of input clock shift.
Linux supports this API through the /sys/ interface using file I/O. First export the pwm channel to enable it:
# Export PWM channel 0
echo 0 > /sys/class/pwm/pwmchip0/export
File | Description |
---|---|
/sys/class/pwm/pwmchip0/pwm0/period | Period in nanoseconds. Must be bigger than the duty cycle or writes will fail. Can only change when the pwm is disabled. |
/sys/class/pwm/pwmchip0/pwm0/duty_cycle | Duty cycle in nanoseconds. Can change at any time, must be less than period. |
/sys/class/pwm/pwmchip0/pwm0/enable | When 1, pwm is outputting. When 0, outputs idle state of the PWM. |
/sys/class/pwm/pwmchip0/pwm0/polarity | When "normal", idle high and duty cycle low. When "inversed", idle low and duty cycle high. A valid period must be set before this can be changed. |
For example, for a 50hz signal with 25% duty cycle:
# Set Period to 20ms
echo 20000000 > /sys/class/pwm/pwmchip0/pwm0/period
# Set duty cycle to 5ms
echo 5000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
# Enable PWM and output 50hz signal
echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
# Duty cycle can be changed while it is enabled
echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
The Linux PWM API will attempt to arrive at the exact period at the cost of the duty cycle resolution. For the most possible duty cycle resolution use one of the max period ns values from the table below.
Shift | PWM Input Frequency (hz) | Max Period (ns) | Max Period (hz) |
---|---|---|---|
0 | 79200000 | 12917 | 77419 |
1 | 39600000 | 25833 | 38710 |
2 | 19800000 | 51667 | 19355 |
3 | 9900000 | 103333 | 9677 |
4 | 4950000 | 206667 | 4839 |
5 | 2475000 | 413333 | 2419 |
6 | 1237500 | 826667 | 1210 |
7 | 618750 | 1653333 | 605 |
8 | 309375 | 3306667 | 302 |
9 | 154687 | 6613333 | 151 |
10 | 77343 | 13226795 | 76 |
11 | 38671 | 26453932 | 38 |
If period is set to one of these values, the full 10 bits of duty cycle is available. Past that, the Linux API will use the closest available value. Debug output can be enabled with:
echo "file pwm-ts.c +p" > /sys/kernel/debug/dynamic_debug/control
If this is enabled, the kernel can output additional information after setting a frequency:
echo 0 > /sys/class/pwm/pwmchip0/export
# 10ms period:
echo 10000000 > /sys/class/pwm/pwmchip0/pwm0/period
# 5ms duty cycle:
echo 5000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
dmesg | tail
This will output:
[ 75.758146] ts-pwm 500001a8.mikro_pwm: cycle=1293661 shift=10 cnt=773 [ 75.758184] ts-pwm 500001a8.mikro_pwm: shift=10 cnt=773 duty_cnt=387
The last value in cnt indicates how much resolution is available for the duty cycle at this given period. In the best case there are 10 bits (0-2047) to specify duty cycle, but this above example is 0-773 to arrive at this particular period. You can determine the duty cycle increments with period / cnt. From the above example:
10000000 / 773 = 12936.61
The duty cycle can then be configured in increments of 12936ns. Smaller values will round to the closest value.
This PWM will allow a max speed of 79.2MHz / 3 = 26.4MHz, but this will sacrifice all of the available duty cycle except an on/50%/off. The slowest speed is highest divisor at 38hz.
While the Linux driver is recommended for most users, the PWM core is located at 0x500001a8.
Offset | Bits | Description |
---|---|---|
0x0 | 15:2 | Reserved |
1 | Inversed (0 = idle high, duty cycle low), (1 = idle low, duty cycle high) | |
0 | Enabled | |
0x2 | 15:10 | Reserved |
9:0 | Period | |
0x4 | 15:10 | Reserved |
9:0 | Duty Cycle | |
0x6 | 15:4 | Reserved |
3:0 | shift (Clock frequency = 79200000 / (1 >> shift)) |