Page 1 of 2

LED dimm with gpio-pwm

Posted: Sat Dec 27, 2014 10:03 am
by aheitz
Hello,

I Compiled the pwm Module into the vocore Image from this description:
http://vonger.cn/?topic=pwm-is-running-at-gpios.
And i simple connect an LED to gpio17 but the LED is flickering iregulary. Does anyone have an idea where the reason could be?

Greetings Andreas

Re: LED dimm with gpio-pwm

Posted: Sun Dec 28, 2014 12:45 pm
by Vonger
do you try another GPIO?

Re: LED dimm with gpio-pwm

Posted: Sun Dec 28, 2014 4:25 pm
by aheitz
I tried gpio 20, 21 and 12 and i had the same behaviour.
I started and stopped wit this script:
First:
Code: Select all
mount -t configfs none /config

To start:
Code: Select all
GPIO=12
mkdir /config/gpio_pwm/$GPIO
echo 1 > /sys/class/pwm/gpio_pwm\:$GPIO/export
echo 10000000 > /sys/class/pwm/gpio_pwm\:$GPIO/period_ns
echo 5000000 > /sys/class/pwm/gpio_pwm\:$GPIO/duty_ns
echo 1 > /sys/class/pwm/gpio_pwm\:$GPIO/run

And finally to stop:
Code: Select all
echo 0 > /sys/class/pwm/gpio_pwm\:$GPIO/run
echo 1 > /sys/class/pwm/gpio_pwm\:$GPIO/unexport
rm -rf /config/gpio_pwm/$GPIO

I want to use the PWM for control 8 - 10 Power LED with an MOSFET for switching the Power LEDs.
For testing i use an LED and 330 Ohm Resitor direct on the GPIO. Do you think that it is possible to use the VoCore for this?

Re: LED dimm with gpio-pwm

Posted: Mon Dec 29, 2014 4:13 pm
by Ton
I have the same problem. It looks as if there is another (1 hz?) signal superimposed over the generated pwm signal.

In DMESG I see this:

Code: Select all


[    0.000000] genirq: Flags mismatch irq 7. 00014600 (timer) vs. 00014600 (systick)



I guess that means there is an IRQ conflict.

In other DTS files for the RT5350 I see the following entries:


Code: Select all

 timer@100 {
           compatible = "ralink,rt5350-timer", "ralink,rt2880-timer";
           reg = <0x100 0x20>;
           interrupt-parent = <&intc>;
           interrupts = <1>;
   };


   systick@d00 {
           compatible = "ralink,rt5350-systick", "ralink,cevt-systick";
           reg = <0xd00 0x10>;

           interrupt-parent = <&cpuintc>;
           interrupts = <7>;
   };


I did not try to add these entries to the dts file yet.

Vonger, do you think this is needed?

Re: LED dimm with gpio-pwm

Posted: Mon Dec 29, 2014 9:40 pm
by Greenwire-Elektronik
I just checked with the datasheet - there is no hardware solution for GPIO PWM, this means it is a pure software solution. You can probably check the files which have to handle it. If i find some spare minutes tomorrow, i will have a deeper look into it.

Re: LED dimm with gpio-pwm

Posted: Thu Jan 01, 2015 11:28 am
by Ton
I added the
Code: Select all
timer@100 {
      .....see above
   };
systick@d00 {
      .....see above
   };

part to the DTS file. Building goes ok, but no difference, still an unregular signal on the LED,
and still genirq: Flags mismatch irq 7 in DMESG.

Re: LED dimm with gpio-pwm

Posted: Thu Jan 01, 2015 4:31 pm
by Greenwire-Elektronik
Ton,

you do not have to rebuild - the quoted part is automatically imported for vocore.dts caused by row 3 (/include/ "rt5350.dtsi").
The important line out of
https://github.com/openwrt-mirror/openw ... t5350.dtsi
is row 190
interrupts = <7>


So the problem is narrowed down for the system tick. I assume the PWM function (which i previously stated is not directly implemented in hardware) is realized with the free running counter - see Chapter 3.6 especially the register offset 0x0h and 0x4h. I think kernel is loading 0x4h with the given value (your time value divided by the system tick time) and after this enabling 0x0h:CNT_EN. After the specific time, the interrupt 7 will be generated.
So far so good.
Let's cut to the error message.
The systemtick is handled by a driver generated through this patch:
https://github.com/openwrt-mirror/openw ... ling.patch
The patch leads to:
https://github.com/torvalds/linux/blob/ ... t-rt3352.c
This file configures systemtick to irq 7 and to external timer interrupt (EXT_STK_EN=1).

I haven't found something exactly sticking to the problem, so i just searched in the kernel sources for the error message prefix "Flags mismatch irq".
I found the file which seems to manage interrupts and generate the messages:
https://github.com/torvalds/linux/blob/ ... q/manage.c
There is more or less just one case which can lead to this message, it begins around row 1050 and i checks for interrupt sharing and level (i think).

I have the feeling that the normal timer interrupt is somehow interfering with that systemtick.
Next step would be register dumping and going through it step by step. i have not vocore to hand though, so i cannot do it - Ton?
What could be needed: All registers from the interrupt controller (0x10000200h base), from the timer (0x10000100h base) and the systemtick (0x10000d00h base). Best time slot to dump is after configuring but not starting the PWM.

So far sorry for not have a solution in hand, but i think this might give new ideas.

Best Regards,

Jonas

Re: LED dimm with gpio-pwm

Posted: Sat Jan 03, 2015 1:14 pm
by Ton
Hi Jonas,

I have a vocore available, but how to dump the registers? Is there a tool?

Re: LED dimm with gpio-pwm

Posted: Sat Jan 03, 2015 3:38 pm
by Greenwire-Elektronik
Hi Ton,

no, you need to write a c program.
What you need:

Code: Select all
int* memaccess;
int fd = open("/dev/mem", O_RDWR);
int dumpvalue;

...

if (fd == -1) {
printf("Error getting mem access\n");
return -1;
}
else
memaccess = (unsigned int*) mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x10000000);
close(fd);

dumpvalue=memaccess[OFFSET>>2]; //OFFSET means the address offset from 0x10000000 in hex, for gpio register GPIO21_00_EDGE it would be 0x604.


This would dump the content of GPIO21_00_EDGE into dumpvalue. It is a lot of copy paste for those dumps i admit.

Rgds

Jonas

Re: LED dimm with gpio-pwm

Posted: Sun Jan 04, 2015 1:59 pm
by Ton
Hi Jonas,

These are the registers:

Code: Select all
Before PWM:

 0100 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0110 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0114 - 0000FFFF - 0000_0000_0000_0000_1111_1111_1111_1111
 0118 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0120 - 0000D692 - 0000_0000_0000_0000_1101_0110_1001_0010
 0124 - 0000D148 - 0000_0000_0000_0000_1101_0001_0100_1000
 0128 - 000000BF - 0000_0000_0000_0000_0000_0000_1011_1111
 0200 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0204 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0220 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0230 - 00000008 - 0000_0000_0000_0000_0000_0000_0000_1000
 0234 - 80061042 - 1000_0000_0000_0110_0001_0000_0100_0010
 0238 - 80061042 - 1000_0000_0000_0110_0001_0000_0100_0010
 0D00 - 00000003 - 0000_0000_0000_0000_0000_0000_0000_0011
 0D04 - 0000B514 - 0000_0000_0000_0000_1011_0101_0001_0100
 0D08 - 0000B380 - 0000_0000_0000_0000_1011_0011_1000_0000
root@Vocore2:~#

After:

 0100 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0110 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0114 - 0000FFFF - 0000_0000_0000_0000_1111_1111_1111_1111
 0118 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0120 - 0000D692 - 0000_0000_0000_0000_1101_0110_1001_0010
 0124 - 0000D351 - 0000_0000_0000_0000_1101_0011_0101_0001
 0128 - 000000BF - 0000_0000_0000_0000_0000_0000_1011_1111
 0200 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0204 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0220 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0230 - 00000008 - 0000_0000_0000_0000_0000_0000_0000_1000
 0234 - 80061042 - 1000_0000_0000_0110_0001_0000_0100_0010
 0238 - 80061042 - 1000_0000_0000_0110_0001_0000_0100_0010
 0D00 - 00000003 - 0000_0000_0000_0000_0000_0000_0000_0011
 0D04 - 00000B09 - 0000_0000_0000_0000_0000_1011_0000_1001
 0D08 - 00000AEC - 0000_0000_0000_0000_0000_1010_1110_1100
root@Vocore2:~#


Another vocore: (Standard .dts file)

 0100 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0110 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0114 - 0000FFFF - 0000_0000_0000_0000_1111_1111_1111_1111
 0118 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0120 - 0000D692 - 0000_0000_0000_0000_1101_0110_1001_0010
 0124 - 0000CD16 - 0000_0000_0000_0000_1100_1101_0001_0110
 0128 - 000000BF - 0000_0000_0000_0000_0000_0000_1011_1111
 0200 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0204 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0220 - 00000000 - 0000_0000_0000_0000_0000_0000_0000_0000
 0230 - 00000008 - 0000_0000_0000_0000_0000_0000_0000_1000
 0234 - 80061042 - 1000_0000_0000_0110_0001_0000_0100_0010
 0238 - 80061042 - 1000_0000_0000_0110_0001_0000_0100_0010
 0D00 - 00000003 - 0000_0000_0000_0000_0000_0000_0000_0011
 0D04 - 00000C25 - 0000_0000_0000_0000_0000_1100_0010_0101
 0D08 - 00000B62 - 0000_0000_0000_0000_0000_1011_0110_0010
root@Vocore1:~/dumpert#


0124 is a running timer, D04 and D08 are running as well.

All values seem ok.

Code to generate the dump:


Code: Select all
/*
 * Simple Q&D dumper for some RT5350 registers
 * Ton Augustin - 2015
 *
 */
 
 
#include <sys/mman.h>
#include <stdio.h>      // printf
#include <string.h>     // strcat
#include <stdlib.h>     // strtol
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


const char *int32_to_binary(unsigned int x)
{
  static char b[50];
  b[0] = '\0';
  unsigned int z;
  int hick;
  hick = 0;
  for (z = 0x80000000; z > 0; z >>= 1)
  {
    strcat(b, ((x & z) == z) ? "1" : "0");
    hick++;
    if((hick == 4)&&(z != 1)) {
        strcat(b, "_");
        hick = 0;
    };
  }

  return b;
}


main() {

int* memaccess;
int fd = open("/dev/mem", O_RDWR);
int dumpvalue;


if (fd == -1) {
   printf("Error getting mem access\n");
   return -1;
}
memaccess = (unsigned int*) mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x10000000);

void writevalues( int offst) {
   dumpvalue=memaccess[offst>>2]; //OFFSET means the address offset from 0x10000000 in hex, for gpio register GPIO21_00_EDGE it would be 0x604.
   printf(" %04X - %08X - %s\n", offst, dumpvalue, int32_to_binary((unsigned int)dumpvalue));
}


//timer 0x100
writevalues(0x00 + 0x100);
writevalues(0x10 + 0x100);
writevalues(0x14 + 0x100);
writevalues(0x18 + 0x100);
writevalues(0x20 + 0x100);
writevalues(0x24 + 0x100);
writevalues(0x28 + 0x100);

//int 0x200
writevalues(0x00 + 0x200);
writevalues(0x04 + 0x200);
writevalues(0x20 + 0x200);
writevalues(0x30 + 0x200);
writevalues(0x34 + 0x200);
writevalues(0x38 + 0x200);

//sys 0xD00
writevalues(0x00 + 0xD00);
writevalues(0x04 + 0xD00);
writevalues(0x08 + 0xD00);

close(fd);

}