Heatermeter on new small-footprint platform: HLK-RM04 (RT5350 based)


 

Fredrik O

New member
Hi,

I'm new here. Been using the Heatermeter 4.0 with a RPi since April with some great ribs and pulled pork as a result. Thanks for your superb work Bryan!

I've been experimenting with a HLK-RM04 module with stock 16MB RAM and 4MB flash. The unit (the white labeled package in the picture) is mounted on a development kit with a wan and a lan port well as an RS232 port (assigned to the console for diagnostic purposes).

OpenWrt:
Barrier Breaker, r39237 (the first release with support for the HLK-RM04)
Luci 0.11.1

In order to make Linkmeter run on the board, I've made some mods:
Linkmeter config: Heatermeter serial port changed from ttyS1 to ttyS0
Busybox default config: Enabled support for stty (the detailed Busybox configuration is not included in Menuconfig for r39237)
Linkmeterd.lua: Disabled the function postDevice Data (specifically designed for the RPi) in order for lucid being able to start

I get the combo working including graphs from the Heatermeter and configuration changes to the Heatermeter, however, only over the lan port. When enabling the wifi, the HLK reboots after a short while, most probably due to memory starvation. That should be the next thing to fix if possible. If not, one has to replace the RAM chip with a 32MB one.

XVevMCd.jpg
VnD4RJZ.jpg
 
Last edited:
That's awesome that it works, definitely good to see that it works. I've pushed a change that may or may not fix the crashing when writing out the HeaterMeter Live device data for this new chip.

I probably won't be going exactly this direction, because the HLK-RM04 modules don't have their SPI bus pins exposed so it isn't possible to flash a blank ATmega with HeaterMeter. Also the problem with rebooting after a while. Hopefully that's better with the 32MB RAM VoCore modules I'll be trying out later this year.
 
Oh wow, thats exactly what I have been working on. Well, I'm mostly waiting for my HLK-RM04 any my custom PCBs to arrive from China.

Would you mind sharing your changes or at least your ".config" file for OpenWRT so I don't have to duplicate the work?

As for RAM starvation, do you have zram enabled? It might help with that.

As for programming the ATmega for the first time, you can bit bang the SPI. It won't be very fast, but you only need to do it a single time anyways.
Vocore is still the superior device of course.
 
Many thanks for the feedback! And the quick linkmeterd patch!
I'll be more than happy to share the details when I have worked my way through the busy week I have ahead of me.
There's a new version of the HLK-RM04 with 8MB flash and 32MB RAM. I've ordered two units from China, will be here in a few weeks time.
 
Linkmeter on HLK-RM04, necessary mods:

Use Bleeding Edge r39237 and the latest Linkmeter update, including Bryans RT5350 patch

linkmeter.uci-defaults, change tty port:
Code:
SERIAL_DEVICE="/dev/ttyS0"

Bryan's install.sh modified such that:
Code:
#!/bin/sh

REPO_PATH=$(pwd)
TARGET="$1"
WRT_PATH="$2"

if [ -z "$WRT_PATH" ] ; then
  echo "Usage: ./install.sh <target> <wrt path>"
  echo "    Target: BCM47XX, BCM2708 or HLKRM04 (case sensitive)"
  echo "BCM47XX - svn://svn.openwrt.org/openwrt/trunk@29665"
  echo "BCM2708 - svn://svn.openwrt.org/openwrt/tags/attitude_adjustment_12.09"
  echo "HLKRM04 - svn://svn.openwrt.org/openwrt/trunk@39237"
  exit 1
fi

if [ "$TARGET" = "BCM47XX" ] ; then
  cat << EOFEEDS > $WRT_PATH/feeds.conf
src-svn packages svn://svn.openwrt.org/openwrt/packages@29665
src-svn luci http://svn.luci.subsignal.org/luci/trunk/contrib/package@8686
src-link linkmeter $REPO_PATH/package
EOFEEDS
fi

if [ "$TARGET" = "BCM2708" ] ; then
  cat << EOFEEDS > $WRT_PATH/feeds.conf
src-svn packages svn://svn.openwrt.org/openwrt/branches/packages_12.09
src-svn luci http://svn.luci.subsignal.org/luci/tags/0.11.1/contrib/package
src-link linkmeter $REPO_PATH/package
EOFEEDS
fi

if [ "$TARGET" = "HLKRM04" ] ; then
  cat << EOFEEDS > $WRT_PATH/feeds.conf
src-svn packages svn://svn.openwrt.org/openwrt/packages@39237
src-svn luci http://svn.luci.subsignal.org/luci/tags/0.11.1/contrib/package
src-link linkmeter $REPO_PATH/package
EOFEEDS
fi


$WRT_PATH/scripts/feeds update

LUCIP=$WRT_PATH/feeds/luci/luci/patches
rm -fR $LUCIP
mkdir $LUCIP
cp patches/200-luci-inreq-fix.patch $LUCIP
cp patches/215-luci-adminfull-inreq.patch $LUCIP
cp patches/217-luci-login-urltok.patch $LUCIP
cp patches/218-lucid-cacheloader.patch $LUCIP
cp patches/219-lucid-sysupgrade-url.patch $LUCIP
cp patches/226-lucid-no-redirect.patch $LUCIP
cp patches/227-lucid-keepalive-fix.patch $LUCIP
cp patches/228-luci-no-dhcp-dhcpc.patch $LUCIP

LMPACKS="rrdtool linkmeter luci-app-msmtp parted avahi-daemon kmod-incompat-wireless"
for PACK in $LMPACKS ; do
  $WRT_PATH/scripts/feeds install -p linkmeter $PACK
done

cp config.$TARGET $WRT_PATH/.config

if [ "$TARGET" = "BCM47XX" ] ; then
  patch -N -p0 -d $WRT_PATH/package < patches/100-dhcp_add_hostname.patch
fi

if [ "$TARGET" = "BCM2708" ] ; then
  patch -N -p0 -d $WRT_PATH < patches/0700-bcm2708-tweaks.patch
  patch -N -p0 -d $WRT_PATH < patches/110-dnsmasq_add_hostname.patch
  patch -N -p0 -d $WRT_PATH < patches/220-iwinfo-nl80211-over-wext.patch
  patch -N -p0 -d $WRT_PATH < patches/225-iwinfo-scan-wo-vintf.patch
  cp patches/06??-rpi-patches-*.patch \
    $WRT_PATH/target/linux/brcm2708/patches-3.3/.
fi
.config: Copy Bryan's template config.BCM47XX to config.HLKRM04

/openwrt/package/utils/busybox/config/default, add stty support:
Code:
CONFIG_STTY=y
In menuconfig choose:
  • Target System (Ralink RT288x/RT3xxx)
  • Subtarget (RT3x5x/RT5350 based boards)
  • Target Profile (HILINK HLK-RM04)


That should be it!
 
Thanks for sharing!

I got my custom PCBs, but I'm still waiting for my HLK-RM04, so I still can't test it.

I'll post an update when I have it.
 
I got my HLK-RM04 with 32M RAM from China today. Couldn't wait to test it, so I flashed a new bootloader (uboot256), changed the memory size in HLKRM04.dts file to 32M and remade the image (no other changes relative to my previous post).

The result is great: Linkmeter runs flawlessly, even on wireless! No memory starvation noticable. I haven't yet connected the Heatermeter, but I don't expect any problems.:cool:
 
Further testing the HLK-RM04, 32M RAM, with Linkmeter/Heatermeter:

It works fine with Heatermeter using wifi and, after patching the linkmeter Makefile to allow for simple wifi-mode switching, it's happily switching between access point and client mode:

Code:
-   if [ "$(CONFIG_TARGET_brcm2708)" = "y" ]
+   if [ "$(CONFIG_TARGET_brcm2708)" = "y" ] || [ "$(CONFIG_TARGET_ramips)" = "y" ]

I've been running the combo for some hours and the long term stability seems to be there.

It looks as if the main missing functionality with respect to a RPi setup is the ATmega flashing capability.
 
Also check openwrt/package/linkmeter/config/linkmeter.uci-defaults because there's a lot of things it sets up depending on the platform. You'll probably want something closer to the default options rather than the BCM2708 because of the memory constraints.

Possible other missing functionality would be sysupgrade support for being able to do a live update to OpenWrt firmware without losing your configuration.
 
An update:

On the 32M hlk-rm04 I have now used avrdude-6.0.1 in linuxgpio mode to flash the atmega. Due to the limited number of exposed gpio pins on the hlk, I had to sacrifice the uartf, meaning that there is just one physical serial port, and use those pins as gpio. The gpio configuration is done in HLK-RM04.dts.

There seems to be a bug in avrdude such that it's not possible to run it twice without rebooting between the runs. The gpios remain exported after the first run, blocking a renewed export request.

Next step is trying to patch Bryan's avrupdate such that it calls avrdude instead of hmdude.
 
The command lines are compatible I'm pretty sure so you can just replace hmdude with avrdude. Your avrdude probably needs a couple other options though, but at least the common part should be fine.
 
Yes, flashing the AVR works fine replacing hmdude with avrdude!

Besides adjusting the options in avrupdate, I had to disable part of avrdude's exit routine where it performs an unexport of the gpios. Apparently, there is a bug on the openwrt side when unexporting gpios on the RT5350. It is not possible to do more than one export/unexport cycle per gpio from the console before exporting action is blocked.
 
Have you tried sysupgrade support at all? I'm wondering if it will be possible to upgrade the firmware without having do any tftp shenanigans.
 
Yes, sysupgrade works fine when openwrt is up and running. The bootloader must be replaced from start and when loading the first openwrt image, I know of no other way than via tftp.

I'm currently trying to push the RT5350 into the combined uartf/gpio mode such that it would be possible to maintain two physical ttys while having enough gpios for the avrdude. There is a bug somewhere in the pinctrl part, probably in pinctrl-rt2880.c. The pin map in the pin mux is screwed up in the sense that the pin count for I/O function n is in fact the pin count for function n+3 which in turn makes it impossible to configure the combined uartf/gpio mode that should be available from the RT5350. It's a bit time consuming because I'm still struggling with getting used to C programming. I haven't been programming seriously since Pascal and assembler was the name of the game!
 
Last edited:
The combined uartf/gpio mode is now working, done by patching the pinctrl driver pinctrl-rt2880.c:
Code:
 		/* mark the pins as gpio */
 		for (i = 0; i < p->groups[group].func[0].pin_count; i++)
 			p->gpio[p->groups[group].func[0].pins[i]] = 1;
-	} else {
+	}
+	/* combined uartf and gpio function */
+	else if ((p->groups[group].name == "uartf") && (p->func[func]->pin_count == 4)) {
+		int i, first_gpio_pin;
+
 		mode |= p->func[func]->value << p->groups[group].shift;
+		if (p->func[func]->pin_first == 7) {
+			first_gpio_pin = p->func[func]->pin_first + 4;
+		}
+		else {
+			first_gpio_pin = p->func[func]->pin_first - 4;
+		}
+		/* mark the pins as gpio */
+		for (i = first_gpio_pin; i < (first_gpio_pin + 4); i++)
+			p->gpio[i] = 1;
 	}
+	/* other */
+	else {
+		mode |= p->func[func]->value << p->groups[group].shift;
+	}
+
 	rt_sysc_w32(mode, SYSC_REG_GPIO_MODE);

and a small fix in the rt5350.dtsi:

Code:
		uartf_pins: uartf {
			uartf {
				ralink,group = "uartf";
-				ralink,function = "uartf";
+				ralink,function = "gpio uartf";
			};
		};
	};

The above makes it possible to use the four gpios exposed, gpio0, 1, 2 and 14, to be used by avrdude.
Since avrdude has difficulties handling gpio0 in the linuxgpio mode, I had to make a dirty fix in avrdude such that the used pins are numbered X+1 when using gpios X. This is done in linuxgpio.c such that all calls to gpios vis sysfs are done as gpio-1.

The HLK-RM04 now works fine with heatermeter including the AVR firmware update functions and there are two ttys availabe.
 
I have added some functionality to hmdude (basically a new version of the spi_transaction function and some initialization stuff) such that it is now possible to use it with the four exposed gpios (0, 1, 2, 14) of the HLK-RM04. The AVR firmware upgrade works flawlessly from within linkmeter!
 
That's awesome! Is it pretty quick still? I was wondering about the speed of the GPIO interface. Do you use the sysfs interface or some sort of API?

I recently employed another atheros box to interface my electric vehicle charger and give it a wifi interface. It is an atheros AR9331 @ 400Mhz with 64MB of RAM and 16MB of flash you can get for $28. Smokin Hardware, Inc has bought me a second to play around with as a HeaterMeter host. It is nice because the UART, GPIO, and power are brought out to headers. It might be a little easier to interface than the HLK-RM04 board and has the ethernet right on it already.
 

 

Back
Top