Welcome to zewaren.net. This site presents myself and mostly archives the solutions to some problems I once had.

How to sign POST requests with OAuth 1.0 using oauth-signpost and HttpURLConnection

Situation

Signpost's documentation states that the library cannot be used along with HttpURLConnection to sign standard POST requests. This is not entirely true.

Method setAdditionalParameters() can be used to add a few parameters to the OAuth base string. The trick is to add them already percent-encoded.

Code sample

package test_oauth;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Iterator;
import java.util.Scanner;

import oauth.signpost.OAuth;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.basic.DefaultOAuthConsumer;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.http.HttpParameters;

public class TestOAuth {

	public static void main(String[] args) throws IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
		final String endpointUrl = "http://some-api.example.org/index.php/api/v1/end/point";

		//Create an HttpURLConnection and add some headers
		URL url = new URL(endpointUrl);
		HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
		urlConnection.setRequestProperty("Accept", "application/json");
		urlConnection.setRequestMethod("POST");
		urlConnection.setDoOutput(true);

		//Build the list of parameters
		HttpParameters params =  new HttpParameters();
		params.put("param1", "49607,49608,49609");
		params.put("param2", "1396430420");
		params.put("param3", "coucou");
		
		//Sign the request
		//The key to signing the POST fields is to add them as additional parameters, but already percent-encoded; and also to add the realm header.
		OAuthConsumer dealabsConsumer = new DefaultOAuthConsumer ("5314c6fbe7437", "5314c6fbe7bfd");
		HttpParameters doubleEncodedParams =  new HttpParameters();
        Iterator<String> iter = params.keySet().iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            doubleEncodedParams.put(key, OAuth.percentEncode(params.getFirst(key)));
        }
        doubleEncodedParams.put("realm", endpointUrl);
		dealabsConsumer.setAdditionalParameters(doubleEncodedParams);
        dealabsConsumer.sign(urlConnection);
        
        //Create the POST payload
        StringBuilder sb = new StringBuilder();
        iter = params.keySet().iterator();
        for (int i = 0; iter.hasNext(); i++) {
            String param = iter.next();
            if (i > 0) {
                sb.append("&");
            }
            sb.append(params.getAsQueryString(param, false));  
        }
        
        //Send the payload to the connection
        String formEncoded = sb.toString();;
		OutputStreamWriter outputStreamWriter = null;
        try {
            outputStreamWriter = new OutputStreamWriter(urlConnection.getOutputStream(), "UTF-8");
            outputStreamWriter.write(formEncoded);
        } finally {
            if (outputStreamWriter != null) {
                outputStreamWriter.close();
            }
        }
        
        //Send the request and read the output
		try {
			System.out.println("Response: " + urlConnection.getResponseCode() + " " + urlConnection.getResponseMessage());
			InputStream in = new BufferedInputStream(urlConnection.getInputStream());
			String inputStreamString = new Scanner(in,"UTF-8").useDelimiter("\\A").next();
			System.out.println(inputStreamString);
		}
		finally {
			urlConnection.disconnect();
		}
	}

}

This code was tested on Java 7 on a PC, and on Android.

How to have cpuminer use all CPUs on FreeBSD

Image

Situation

You're trying to mine some cryptocoins on your FreeBSD box. Unfortunately, the mining process seems to occur on only one CPU, despite cpuminer creating and binding threads.

[2014-03-23 01:41:53] 8 miner threads started, using 'X11' algorithm.
[2014-03-23 01:41:53] Starting Stratum on stratum+tcp://drkpool.com:3333
[2014-03-23 01:41:53] Binding thread 0 to cpu 0
[2014-03-23 01:41:53] Binding thread 1 to cpu 1
[2014-03-23 01:41:53] Binding thread 2 to cpu 2
[2014-03-23 01:41:53] Binding thread 3 to cpu 3
[2014-03-23 01:41:53] Binding thread 4 to cpu 4
[2014-03-23 01:41:53] Binding thread 5 to cpu 5
[2014-03-23 01:41:53] Binding thread 6 to cpu 6
[2014-03-23 01:41:53] Binding thread 7 to cpu 7
[2014-03-23 01:41:56] Stratum detected new block

Using ktrace yields some information. The thread-cpu binding is failing.

 23429 minerd   CALL  write(0x2,0x7fffff5fa660,0x30)
 23429 minerd   GIO   fd 2 wrote 48 bytes
       "[2014-03-23 00:45:32] Binding thread 1 to cpu 1
       "
 23429 minerd   RET   write 48/0x30
 23429 minerd   CALL  _umtx_op(0x803019060,0x16,0,0,0)
 23429 minerd   RET   _umtx_op 0
 23429 minerd   CALL  cpuset_setaffinity(0x3,0x3,0xffffffffffffffff,0x10,0x7fffff5faf70)
 23429 minerd   RET   cpuset_setaffinity -1 errno 11 Resource deadlock avoided
 23429 minerd   CALL  nanosleep(0x7fffff5fad90,0x7fffff5fad80)
 23429 minerd   RET   _umtx_op 0
 23429 minerd   CALL  mmap(0,0x400000,0x3<PROT_READ|PROT_WRITE>,0x1002<MAP_PRIVATE|MAP_ANON>,0xffffffff,0)
 23429 minerd   RET   mmap 34431041536/0x804400000
 23429 minerd   CALL  _umtx_op(0x803019060,0x16,0,0,0)
 23429 minerd   RET   _umtx_op 0

Solution

Use cpuset to change the affinity of the process once it's launched.

cpuset -c -l 0-15 -p 3044

Adapt the command to your number of CPUs and the PID of your miner process.

See kern/163585 for more information.

How to connect to a MySQL/MariaDB server with PHP using the dialog plugin.

Situation

You want to authenticate your MySQL/MariaDB users using an authentication plugin (for instance: pam). This kind of auth uses the dialog plugin. You can login using the mysql command line client and using Perl's DBI, but not without PHP.

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client'

Solution

PHP now uses its own MySQL driver (mysqlnd), instead of the good old libmysqlclient.

The solution is to rebuild PHP using the right configure options.

                --enable-pdo \
                --with-mysqli=/usr/local/bin/mysql_config \
                --with-pdo-mysql=/usr/local/bin/mysql_config \

Reference: http://dev.mysql.com/doc/apis-php/en/apis-php-mysqli.installation.linux.html

How to use Wireshark on Windows to watch a remote UNIX system, using SSH

Wireshark&#039;s pipe interface

Situation

You're using tcpdump on a UNIX box but you would like to use Wireshark for all its awesome features (gui, analysis, etc.) on your local Windows desktop computer.

Solution

Connect to your box using SSH and pipe the output of tcpdump into wireshark.

"c:\Program Files (x86)\PuTTY\plink.exe" -ssh root@my-unix-box.example.com "tcpdump -w - -s 65535 [tcpdump condition] " | "c:\Program Files\Wireshark\wireshark.exe" -i -

plink is bundled with putty, but you can download it separatly.

How to get rid of "Warning: using insecure memory" using spamassasin on FreeBSD

Situation

You run sa-update periodically and in your logs you get some lousy:

Warning: using insecure memory! 

Fix

The well known fix is to add some option into the gpg configuration file.

The key is to know where to find it:

/usr/local/etc/mail/spamassassin/sa-update-keys/gpg.conf

no-secmem-warning

How to create a rar file with every file matching a pattern (including subdirectories) on Windows

Creating the rar file

How to create a rar file with any file matching a pattern (including subdirectories) on Windows.

forfiles /s /m wallet.dat /c "cmd /c echo @relpath" | "c:\Program Files\WinRAR\Rar.exe" a -dh -rr524288 wallets.rar @

RAR 4.20   Copyright (c) 1993-2012 Alexander Roshal   9 Jun 2012
Registered to zewaren

Updating archive wallets.rar

Updating  .\Alphacoin\wallet.dat                                      OK
Updating  .\AmericanCoin\wallet.dat                                   OK
Updating  .\AndroidsToken\wallet.dat                                  OK
Updating  .\Betacoin\wallet.dat                                       OK
Updating  .\Bitcoin\wallet.dat                                        OK
Updating  .\Colossuscoin\wallet.dat                                   OK
Updating  .\digitalcoin\wallet.dat                                    OK
Updating  .\eMark\wallet.dat                                          OK
Updating  .\Fastcoin\wallet.dat                                       OK
Updating  .\Feathercoin\wallet.dat                                    OK
Updating  .\Florincoin\wallet.dat                                     OK
Updating  .\Franko\wallet.dat                                         OK
Updating  .\Gridcoin\wallet.dat                                       OK
Updating  .\IncaKoin\wallet.dat                                       OK
Updating  .\Litecoin\wallet.dat                                       OK
Updating  .\Luckycoin\wallet.dat                                      OK
Updating  .\Namecoin\wallet.dat                                       OK
Updating  .\NetCoin\wallet.dat                                        OK
Updating  .\NovaCoin\wallet.dat                                       OK
Updating  .\Ocoin\wallet.dat                                          OK
Updating  .\Phoenixcoin\wallet.dat                                    OK
Updating  .\PPCoin\wallet.dat                                         OK
Updating  .\Primecoin\wallet.dat                                      OK
Updating  .\Protoshares\wallet.dat                                    OK
Updating  .\Redcoin\wallet.dat                                        OK
Updating  .\RoyalCoin\wallet.dat                                      OK
Updating  .\Terracoin\wallet.dat                                      OK
Updating  .\Worldcoin\wallet.dat                                      OK
Updating  .\YaCoin\wallet.dat                                         OK
Updating  .\Sexcoin\wallet.dat                                        OK
Done

This example will find any file named wallet.dat and include it in the rar file. You can use wildchars in the pattern.

This will preserve the directory structure.

-dh allows you to add files that are in use by another process.

-rr524288 adds a recovery record to the archive, with the maximum number of sectors (never too cautious).

Checking the rar file

"c:\Program Files\WinRAR\Rar.exe" vb wallets.rar
Alphacoin\wallet.dat
AmericanCoin\wallet.dat
AndroidsToken\wallet.dat
Betacoin\wallet.dat
Bitcoin\wallet.dat
Colossuscoin\wallet.dat
digitalcoin\wallet.dat
eMark\wallet.dat
Fastcoin\wallet.dat
Feathercoin\wallet.dat
Florincoin\wallet.dat
Franko\wallet.dat
Gridcoin\wallet.dat
IncaKoin\wallet.dat
Litecoin\wallet.dat
Luckycoin\wallet.dat
Namecoin\wallet.dat
NetCoin\wallet.dat
NovaCoin\wallet.dat
Ocoin\wallet.dat
Phoenixcoin\wallet.dat
PPCoin\wallet.dat
Primecoin\wallet.dat
Protoshares\wallet.dat
Redcoin\wallet.dat
RoyalCoin\wallet.dat
Terracoin\wallet.dat
Worldcoin\wallet.dat
YaCoin\wallet.dat
Sexcoin\wallet.dat

Image

How to change the icon, version or another resource of Windows executables built with PAR::Packer

Situation

You're using PAR::Packer to create a nice Windows executable out of one of your perl script.

However, the --info and --icon switch aren't working. You might also want to embed some other resource into your executable.

Trying the usual methods

exe_update.pl

exe_update --icon=jambon.ico jambon.exe

exe_update does not work with PAR::Packer executable. It will destroy your file.

ResHacker

ResHacker.exe -modify       "jambon.exe", "jambon.exe", "jambon.ico", ICONGROUP, WINEXE, 0
ResHacker.exe -delete       "jambon.exe", "jambon.exe", versioninfo,1,
ResHacker.exe -addoverwrite "jambon.exe", "jambon.exe", "jambon\version_info.res", versioninfo,1,

ResHacker will edit the resource of your file correctly. However, the executable will error when launching since its signature has changed. This is not acceptable.

Where the icon and version comes from

When built statically, a pp compiled executable is made of data stored in Static.pm, which is made from Static.in and boot.exe. This boot.exe file is the one that contains the final resources.

The resources used to build this file are located in cpan\build\PAR-Packer-1.015-?????\myldr\winres. Modifying these files and rebuilding boot.exe will allow you to change your final executable resources.

The ugly solution that works

Before packing your perl script, rebuild boot.exe with your custom information.

This can easily be automated using a makefile, like this one:

PERL_DIR = C:\StupidPrograms\strawberryperl\perl
PAR_PACKER_SRC = C:\StupidPrograms\strawberryperl\cpan\build\PAR-Packer-1.015-2TLZDS

all:
	copy /Y medias\jambon.ico $(PAR_PACKER_SRC)\myldr\winres\pp.ico
	copy /Y medias\jambon.rc $(PAR_PACKER_SRC)\myldr\winres\pp.rc
	del $(PAR_PACKER_SRC)\myldr\ppresource.coff
	cd /D $(PAR_PACKER_SRC)\myldr\ && perl Makefile.PL
	cd /D $(PAR_PACKER_SRC)\myldr\ && dmake boot.exe
	cd /D $(PAR_PACKER_SRC)\myldr\ && dmake Static.pm
	attrib -R $(PERL_DIR)\site\lib\PAR\StrippedPARL\Static.pm
	copy /Y $(PAR_PACKER_SRC)\myldr\Static.pm $(PERL_DIR)\site\lib\PAR\StrippedPARL\Static.pm

	pp -o jambon.exe -f PodStrip -f Bleach -f Obfuscate --compress=9 jambon.pl

Your perl installation might be different than mine, so you'll want to adapt the scripts.

This solution is quite ugly, but it does work.

How to restart dwm.exe on Windows 8 because it take too much memory

Situation

If you're like me, you seldom restart your desktop computers.

When using Windows 8, I noticed that after a few weeks, the Desktop Window Manager process (C:\Windows\System32\dwm.exe) was taking over a gigabyte of memory. I like my memory, but not when it's used to create memory leaks.

Solution

Kill it with fire.

Using Process Explorer

  1. Start Process Explorer as administrator.
  2. Kill explorer.exe.
  3. Suspend winlogon.exe.
  4. Kill dwm.exe.
  5. Resume winlogon.exe.
  6. Start explorer.exe.

Using command line

taskkill /IM explorer.exe /F
pssuspend.exe winlogon.exe
taskkill /IM dwm.exe /F
pssuspend.exe -r winlogon.exe
dwm.exe
explorer.exe

BeagleBone Black, FreeBSD and GPIOs

The LEDs of a BeagleBone Black running FreeBSD are lighten up. The FreeBSD logo

Introduction

The BeagleBone black, using its AM335X CPU, provides a number of GPIOs. Let's try to make them work.

Trying to find the device

dmesg indicates that the kernel found a GPIO device.

gpio0: <TI General Purpose I/O (GPIO)> mem 0x44e07000-0x44e07fff,0x4804c000-0x4804cfff,0x481ac000-0x481acfff,0x481ae000-0x481aefff irq 96,97,98,99,32,33,62,63 on simplebus0
gpioc0: <GPIO controller> on gpio0
gpiobus0: <GPIO bus> on gpio0

devinfo and ofwdump confirm that the corresponding nodes exist.

# devinfo
nexus0
  fdtbus0
    simplebus0
      aintc0
      ti_scm0
      am335x_prcm0
      am335x_dmtimer0
      gpio0
        gpioc0
        gpiobus0
      uart0
      ti_edma30
      sdhci_ti0
        mmc0
          mmcsd0
      sdhci_ti1
        mmc1
          mmcsd1
      cpsw0
        miibus0
          smscphy0
      iichb0
        iicbus0
          iic0
          am335x_pmic0
      am335x_pwm0
      am335x_pwm1
      am335x_pwm2
      musbotg0
        usbus0
          uhub0
            ustorage_fs0
        usbus1
          uhub1


# ofwdump -a
Node 0x38:
  Node 0xc4: am335x
    Node 0x124: interrupt-controller@48200000
    Node 0x1b4: scm@44e10000
    Node 0xb24: prcm@44E00000
    Node 0xb88: dmtimers@44E05000
    Node 0xc6c: gpio
    Node 0xd14: serial@44E09000
    Node 0xda8: serial@48022000
    Node 0xe54: serial@48024000
    Node 0xf00: serial@481a6000
    Node 0xfac: serial@481a8000
    Node 0x1058: serial@481aa000
    Node 0x1104: edma3@49000000
    Node 0x1188: mmchs0@48060000
    Node 0x120c: mmchs1@481D8000
    Node 0x12a4: ethernet@4A100000
      Node 0x1340: mdio@0
        Node 0x1388: ethernet-phy@0
    Node 0x13c8: i2c@44e0b000
      Node 0x1454: pmic@24
    Node 0x1494: pwm@48300000
    Node 0x1548: pwm@48302000
    Node 0x15fc: pwm@48304000
    Node 0x16b0: lcd@4830e000
    Node 0x1738: usb@47400000
    Node 0x1808: mbox0@480C8000
    Node 0x1874: spinlock0@480CA000
    Node 0x18c0: pruss@4A300000
  Node 0x1944: aliases
  Node 0x198c: memory
  Node 0x19c4: chosen

# ofwdump -p /am335x/gpio
Node 0xc6c: gpio
  #gpio-cells:
    00 00 00 03
  compatible:
    74 69 2c 67 70 69 6f 00
    'ti,gpio'
  gpio-controller:
  reg:
    44 e0 70 00 00 00 10 00 48 04 c0 00 00 00 10 00 48 1a c0 00
    00 00 10 00 48 1a e0 00 00 00 10 00
  interrupts:
    00 00 00 60 00 00 00 61 00 00 00 62 00 00 00 63 00 00 00 20
    00 00 00 21 00 00 00 3e 00 00 00 3f
  interrupt-parent:
    00 00 00 01

Using the device

Reading the kernel source code indicates that the GPIOs are used with a tool called gpioctl.

Listing the available IOs shows that some of them are already configured.

# gpioctl -f /dev/gpioc0 -l
pin 00: 0       gpio_0<>
pin 01: 0       gpio_1<>
pin 02: 0       gpio_2<>
pin 03: 0       gpio_3<>
pin 04: 0       gpio_4<>
pin 05: 0       gpio_5<>
pin 06: 0       gpio_6<>
pin 07: 0       gpio_7<IN,PD>
pin 08: 0       gpio_8<IN>
pin 09: 0       gpio_9<IN>
pin 10: 0       gpio_10<IN>
pin 11: 0       gpio_11<IN>
pin 12: 0       gpio_12<IN,PU>
pin 13: 0       gpio_13<IN,PU>
pin 14: 0       gpio_14<IN,PU>
pin 15: 0       gpio_15<IN,PU>
pin 16: 0       gpio_16<>
pin 17: 0       gpio_17<>
pin 18: 0       gpio_18<>
pin 19: 0       gpio_19<>
pin 20: 0       gpio_20<IN,PD>
pin 21: 0       gpio_21<>
pin 22: 0       gpio_22<>
pin 23: 0       gpio_23<>
pin 24: 0       gpio_24<>
pin 25: 0       gpio_25<>
pin 26: 0       gpio_26<IN,PD>
pin 27: 0       gpio_27<IN,PD>
pin 28: 0       gpio_28<>
pin 29: 0       gpio_29<IN,PD>
pin 30: 0       gpio_30<IN,PU>
pin 31: 0       gpio_31<IN,PU>
pin 32: 0       gpio_32<>
pin 33: 0       gpio_33<>
pin 34: 0       gpio_34<>
pin 35: 0       gpio_35<>
pin 36: 0       gpio_36<>
pin 37: 0       gpio_37<>
pin 38: 0       gpio_38<>
pin 39: 0       gpio_39<>
pin 40: 0       gpio_40<IN,PU>
pin 41: 0       gpio_41<IN,PU>
pin 42: 0       gpio_42<>
pin 43: 0       gpio_43<>
pin 44: 0       gpio_44<IN,PD>
pin 45: 0       gpio_45<IN,PD>
pin 46: 0       gpio_46<IN,PD>
pin 47: 0       gpio_47<IN,PD>
pin 48: 0       gpio_48<IN,PD>
pin 49: 0       gpio_49<IN,PD>
pin 50: 0       gpio_50<>
pin 51: 0       gpio_51<>
pin 52: 0       gpio_52<IN,PD>
pin 53: 0       gpio_53<OUT>
pin 54: 0       gpio_54<OUT>
pin 55: 0       gpio_55<OUT>
pin 56: 0       gpio_56<OUT>
pin 57: 0       gpio_57<IN,PD>
pin 58: 0       gpio_58<IN,PD>
pin 59: 0       gpio_59<IN,PD>
pin 60: 0       gpio_60<IN,PD>
pin 61: 0       gpio_61<IN,PD>
pin 62: 0       gpio_62<>
pin 63: 0       gpio_63<>
pin 64: 0       gpio_64<OUT,PU>
pin 65: 0       gpio_65<IN,PD>
pin 66: 0       gpio_66<>
pin 67: 0       gpio_67<>
pin 68: 0       gpio_68<>
pin 69: 0       gpio_69<IN,PD>
pin 70: 0       gpio_70<IN,PD>
pin 71: 0       gpio_71<IN,PD>
pin 72: 0       gpio_72<IN,PD>
pin 73: 0       gpio_73<IN,PD>
pin 74: 0       gpio_74<IN,PD>
pin 75: 0       gpio_75<IN,PD>
pin 76: 0       gpio_76<IN>
pin 77: 0       gpio_77<IN>
pin 78: 0       gpio_78<IN>
pin 79: 0       gpio_79<>
pin 80: 0       gpio_80<>
pin 81: 0       gpio_81<>
pin 82: 0       gpio_82<>
pin 83: 0       gpio_83<>
pin 84: 0       gpio_84<>
pin 85: 0       gpio_85<>
pin 86: 0       gpio_86<IN,PD>
pin 87: 0       gpio_87<IN,PD>
pin 88: 0       gpio_88<IN,PD>
pin 89: 0       gpio_89<IN,PD>
pin 90: 0       gpio_90<>
pin 91: 0       gpio_91<>
pin 92: 0       gpio_92<>
pin 93: 0       gpio_93<>
pin 94: 0       gpio_94<>
pin 95: 0       gpio_95<>
pin 96: 0       gpio_96<IN,PD>
pin 97: 0       gpio_97<IN,PD>
pin 98: 0       gpio_98<>
pin 99: 0       gpio_99<>
pin 100:        0       gpio_100<>
pin 101:        0       gpio_101<>
pin 102:        0       gpio_102<>
pin 103:        0       gpio_103<>
pin 104:        0       gpio_104<IN,PU>
pin 105:        0       gpio_105<>
pin 106:        0       gpio_106<>
pin 107:        0       gpio_107<>
pin 108:        0       gpio_108<>
pin 109:        0       gpio_109<>
pin 110:        0       gpio_110<IN,PD>
pin 111:        0       gpio_111<IN,PD>
pin 112:        0       gpio_112<IN,PD>
pin 113:        0       gpio_113<IN,PD>
pin 114:        0       gpio_114<>
pin 115:        0       gpio_115<IN,PD>
pin 116:        0       gpio_116<IN,PD>
pin 117:        0       gpio_117<IN,PD>
pin 118:        0       gpio_118<>
pin 119:        0       gpio_119<>
pin 120:        0       gpio_120<>
pin 121:        0       gpio_121<>
pin 122:        0       gpio_122<>
pin 123:        0       gpio_123<>
pin 124:        0       gpio_124<>
pin 125:        0       gpio_125<>
pin 126:        0       gpio_126<>
pin 127:        0       gpio_127<>

Let's try to play with the board's 4 builtin LEDs.

# gpioctl -f /dev/gpioc0 -t 53
# gpioctl -f /dev/gpioc0 -t 54
# gpioctl -f /dev/gpioc0 -t 55
# gpioctl -f /dev/gpioc0 -t 56

Yep, they work.

Let's try configure another random IO.

# gpioctl -f /dev/gpioc0 -c 49 OUT OD
0/OUT
1/OD

GPIO1_17 (P9.23) should be configured as an open-drain output pin. Let's try to change its value.

root@beaglebone:~ # while 1
while? gpioctl -f /dev/gpioc0 -t 49
while? sleep 1
while? end
^C

We created a very slow bit-banged PWM.

Reference and relevant information

BeagleBone Black, FreeBSD and PWMs

Two PWM output from a BeagleBone Black running FreeBSD The FreeBSD logo

Introduction

The BeagleBone black, using its AM335X CPU, provides a number of PWM output. Let's try to make them work.

Trying to find the device

dmesg indicates that the kernel found 3 PWM devices.

am335x_pwm0: <AM335x PWM> mem 0x48300000-0x483000ff,0x48300100-0x4830017f,0x48300180-0x483001ff,0x48300200-0x4830025f irq 86,58 on simplebus0
am335x_pwm1: <AM335x PWM> mem 0x48302000-0x483020ff,0x48302100-0x4830217f,0x48302180-0x483021ff,0x48302200-0x4830225f irq 87,59 on simplebus0
am335x_pwm2: <AM335x PWM> mem 0x48304000-0x483040ff,0x48304100-0x4830417f,0x48304180-0x483041ff,0x48304200-0x4830425f irq 88,60 on simplebus0

devinfo and ofwdump confirm that the corresponding nodes exist.

# devinfo
nexus0
  fdtbus0
    simplebus0
      aintc0
      ti_scm0
      am335x_prcm0
      am335x_dmtimer0
      gpio0
        gpioc0
        gpiobus0
      uart0
      ti_edma30
      sdhci_ti0
        mmc0
          mmcsd0
      sdhci_ti1
        mmc1
          mmcsd1
      cpsw0
        miibus0
          smscphy0
      iichb0
        iicbus0
          iic0
          am335x_pmic0
      am335x_pwm0
      am335x_pwm1
      am335x_pwm2
      musbotg0
        usbus0
          uhub0
            ustorage_fs0
        usbus1
          uhub1


# ofwdump -a
Node 0x38:
  Node 0xc4: am335x
    Node 0x124: interrupt-controller@48200000
    Node 0x1b4: scm@44e10000
    Node 0xb24: prcm@44E00000
    Node 0xb88: dmtimers@44E05000
    Node 0xc6c: gpio
    Node 0xd14: serial@44E09000
    Node 0xda8: serial@48022000
    Node 0xe54: serial@48024000
    Node 0xf00: serial@481a6000
    Node 0xfac: serial@481a8000
    Node 0x1058: serial@481aa000
    Node 0x1104: edma3@49000000
    Node 0x1188: mmchs0@48060000
    Node 0x120c: mmchs1@481D8000
    Node 0x12a4: ethernet@4A100000
      Node 0x1340: mdio@0
        Node 0x1388: ethernet-phy@0
    Node 0x13c8: i2c@44e0b000
      Node 0x1454: pmic@24
    Node 0x1494: pwm@48300000
    Node 0x1548: pwm@48302000
    Node 0x15fc: pwm@48304000
    Node 0x16b0: lcd@4830e000
    Node 0x1738: usb@47400000
    Node 0x1808: mbox0@480C8000
    Node 0x1874: spinlock0@480CA000
    Node 0x18c0: pruss@4A300000
  Node 0x1944: aliases
  Node 0x198c: memory
  Node 0x19c4: chosen

# ofwdump -p /am335x/pwm@48300000
Node 0x1494: pwm@48300000
  compatible:
    74 69 2c 61 6d 33 33 35 78 2d 70 77 6d 00
    'ti,am335x-pwm'
  #address-cells:
    00 00 00 01
  #size-cells:
    00 00 00 01
  reg:
    48 30 00 00 00 00 01 00 48 30 01 00 00 00 00 80 48 30 01 80
    00 00 00 80 48 30 02 00 00 00 00 60
  interrupts:
    00 00 00 56 00 00 00 3a
  interrupt-parent:
    00 00 00 01
  pwm-device-id:
    00 00 00 00

Using the device

There doesn't seem to be much documentation on how to use these devices.

Reading the kernel indicates that the configuration is done using sysctl.

# sysctl -a | grep pwm
"Giant","am335x_pwm softc"
dev.am335x_pwm.0.%desc: AM335x PWM
dev.am335x_pwm.0.%driver: am335x_pwm
dev.am335x_pwm.0.%parent: simplebus0
dev.am335x_pwm.0.period: 1000
dev.am335x_pwm.0.dutyA: 0
dev.am335x_pwm.0.dutyB: 0
dev.am335x_pwm.1.%desc: AM335x PWM
dev.am335x_pwm.1.%driver: am335x_pwm
dev.am335x_pwm.1.%parent: simplebus0
dev.am335x_pwm.1.period: 1000
dev.am335x_pwm.1.dutyA: 0
dev.am335x_pwm.1.dutyB: 0
dev.am335x_pwm.2.%desc: AM335x PWM
dev.am335x_pwm.2.%driver: am335x_pwm
dev.am335x_pwm.2.%parent: simplebus0
dev.am335x_pwm.2.period: 1000
dev.am335x_pwm.2.dutyA: 0
dev.am335x_pwm.2.dutyB: 0

Jackpot! Let's try settings some values in these registers.

# sysctl dev.am335x_pwm.0.period=100
# sysctl dev.am335x_pwm.0.dutyA=50
# sysctl dev.am335x_pwm.0.dutyB=75
# sysctl dev.am335x_pwm.1.period=1000
# sysctl dev.am335x_pwm.1.dutyA=500
# sysctl dev.am335x_pwm.1.dutyB=50
# sysctl dev.am335x_pwm.2.period=250
# sysctl dev.am335x_pwm.2.dutyA=50
# sysctl dev.am335x_pwm.2.dutyB=150

That's it. Probing the pins confirms that the PWM work.

Pin mapping and muxing

Device Pin
sysctl dev.am335x_pwm.1.dutyA P9.14 (ehrpwm1A)
sysctl dev.am335x_pwm.1.dutyB P9.16 (ehrpwm1B)
sysctl dev.am335x_pwm.2.dutyA P8.19 (ehrpwm2A)
sysctl dev.am335x_pwm.2.dutyB P8.13 (ehrpwm2B)

ehrpwm0 is not muxed in the device tree file, so it's not accessible.

Reference and relevant information

Syndicate content