How to overclock the Beaglebone MPU

I was curious if it was possible to overclock the MPU of the beaglebone and, of course it was. 🙂 So here is how I did it. (And be careful, overclocking may damage your beaglebone)

At first i tried to overclock the MPU by manually set the MPU registers. The registers who controls the MPU-freqency is CM_DIV_M2_DPLL_MPU and CM_CLKSEL_DPLL_MPU.

The ADPLLS calculates the MPU clock by following formula:

CLKINP * [1 / (N+1)] * [M] * [1/M2]

CLKINP is the source input-clock, 24.
N is the divider in CM_CLKSEL_DPLL_MPU
M is the multiplier in CM_CLKSEL_DPLL_MPU
M2 is the divider in CM_DIV_M2_DPLL_MPU

Below is the main-function of my program bclock.

int main(int argc, char **argv)
{
	Dpll_mpu* dpll_mpu = malloc(sizeof(Dpll_mpu));
	int fd = open("/dev/mem", O_RDWR); 
	int i;
	if (fd < 0) {
		perror("Could not open file \n");
		return 1;
	}
	
	uint8_t *map; 
	map = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, OFFSET);
	if (map == MAP_FAILED) {
		perror("mmap failed");
		return 1;
	}
	
	get_dpll_mpu(dpll_mpu, map);
	
	if (argc == 1) {
		printf("Usage:  %s [OPTION...]\n  -N, set N-divider\n  -M, set M-multiplier\n \
 -M2, set M2-divider\n", argv[0]);

		get_dpll_mpu(dpll_mpu, map);
		printf("\nCurrent settnings \n-----------------\n");
		print_dpll_mpu(dpll_mpu);
		printf("\nCalculated by formula CLKINP * [1 / (N+1)] * [M]  * [1/M2]\n\n");
	}
	else {
		for (i = 1; i < argc; i+=2)
		{
			if (argc != i+1) {
				if (strcmp(argv[i],"-N") ==  0)
					if (atoi(argv[i+1]) > 0 && atoi(argv[i+1]) <= 0x7f)
						dpll_mpu-> N_divider = atoi(argv[i+1]);
				if (strcmp(argv[i],"-M") == 0)
					if (atoi(argv[i+1]) > 0 && atoi(argv[i+1]) <= 0x3ff)
						dpll_mpu-> M_multiplier = atoi(argv[i+1]);
				if (strcmp(argv[i],"-M2") == 0)
					if (atoi(argv[i+1]) > 0 && atoi(argv[i+1]) <= 0x1f)
						dpll_mpu-> M2_divider = atoi(argv[i+1]);
			}
		}
		
		set_dpll(dpll_mpu,map);
		get_dpll_mpu(dpll_mpu, map);
		print_dpll_mpu(dpll_mpu);
		
	}
	munmap(map, SIZE);	
	close(fd);
	
	free(dpll_mpu);
	return 0;
}

You can overclock the MPU from userspace by writing to the mapped registers. This is what my software bclock does. Try it out and tell me what you think.
Below is the output when running the program.

./bclock
Usage: ./bclock [OPTION...]
-N, set N-divider
-M, set M-multiplier
-M2, set M2-divider

Current settnings
-----------------
CLKINP = 24
N_divider = 2
M_multiplier = 130
M2_divider = 1

MPU frequency = 1040.00 Mhz

Calculated by formula CLKINP * [1 / (N+1)] * [M] * [1/M2]

If you are using cpu-frequency scaling, cpufreq module will overwrite the settnings generated by bclock. You can disable the frequency scaling by set the minimum frequency to maxfrequency, like,
cpufreq-set -d 720Mhz
You can also change the scaling frequencies by modifying the kernelcode in /arch/arm/mach-omap2/opp3xxx_data.c and change the am33xx_opp_def_list structure to the desired frequencies and recompile the kernel. I bought a small heatsink to spead the heat, and so far ive run my MPU at 1040 Mhz successfully.

So does the overclock make any difference? Yes indeed! 🙂
When I’m running 7-Zip benchmark (7zr b) I get the following results:

Orginal @ 720Mhz

Dict        Compressing          |        Decompressing
      Speed Usage    R/U Rating  |    Speed Usage    R/U Rating
       KB/s     %   MIPS   MIPS  |     KB/s     %   MIPS   MIPS

22:     279   100    272    271  |     5442   100    491    491
23:     272   100    277    277  |     5365   100    491    491
24:     263   100    283    283  |     5286   100    490    490
----------------------------------------------------------------
Avr:          100    277    277               100    491    491
Tot:          100    384    384

Overclocked @ 1040Mhz

Dict        Compressing          |        Decompressing
      Speed Usage    R/U Rating  |    Speed Usage    R/U Rating
       KB/s     %   MIPS   MIPS  |     KB/s     %   MIPS   MIPS

22:     356   100    346    346  |     7578   100    684    684
23:     346   100    353    353  |     7451   100    682    682
24:     334   100    360    359  |     7318   100    679    679
----------------------------------------------------------------
Avr:          100    353    353               100    682    681
Tot:          100    517    517 

Be careful, and happy overclocking 🙂
Get the source-code @ gitub.org
Kernel source: AM335x_04_06 04_06_00_08 kernel
TI AM335x Ref Manual

How to make LED-display driver – Beaglebone

I have been playing around with the beaglebone for a while, and the latest project was to make a driver for my 7SEG-LED display using the GPIO ports.
I’m trying to learn more about kernel programming so i made a kernel-module for this task. Its also possible to make a driver like this in userspace, using exported variables in sysfs.

So at first I tried to figure out how to manage the mux configuration from the kernel. Sins the functions in mux.h is’nt exported, i wrote my own routine to set the mux-registers. The function uses the pin_mux structure and set the mux-registers to mux-mode 7 (GPIO).

static int setup_pin_mux(void)
{
	void* adress;
	int i;
	if (request_mem_region(AM33XX_CONTROL_PADCONF_MUX_PBASE, AM33XX_CONTROL_PADCONF_MUX_SIZE,"MuxMem") == NULL)
			printk("Error requesting mem reqion MUX_PBASE\n");

	adress = (void *)ioremap (AM33XX_CONTROL_PADCONF_MUX_PBASE,AM33XX_CONTROL_PADCONF_MUX_SIZE);

	if (adress == NULL)
	{
		printk("Error ioremap: MUX_PBASE\n");
		return -1;
	}

	for (i = 0; pin_mux[i].reg_offset != OMAP_MUX_TERMINATOR; i++)
			iowrite16(pin_mux[i].value, adress+pin_mux[i].reg_offset);

	iounmap(adress);
	release_mem_region(AM33XX_CONTROL_PADCONF_MUX_PBASE,AM33XX_CONTROL_PADCONF_MUX_SIZE);

	return 0;
}

Im using the GPIO ports at the P8 Expansion header. The LEDs are configurated as follow:

  • 3 LED1_1 – GPIO1_6
  • 4 LED1_2 – GPIO1_7
  • 5 LED1_3 – GPIO1_2
  • 6 LED1_4 – GPIO1_3
  • 7 LED1_5 – GPIO2_2
  • 8 LED1_6 – GPIO2_3
  • 9 LED1_7 – GPIO2_5
  • 10 LED1_8 – GPIO2_4
  • 11 LED2_1 – GPIO1_13
  • 12 LED2_2 – GPIO1_12
  • 13 LED2_3 – GPIO0_23
  • 14 LED2_4 – GPIO0_26
  • 15 LED2_5 – GPIO1_15
  • 16 LED2_6 – GPIO1_14
  • 17 LED2_7 – GPIO0_27
  • 18 LED2_8 – GPIO2_1
  • 19 LED1_SWITCH – GPIO0_22 (anode)
  • 20 LED2_SWITCH – GPIO1_31 (anode)

At the LED-display anode, ive put resistors at 480 Ohm, to get safe currents cause maximum output current is 8mA and input 6mA, according to  Gerald Coley. To calculate the resistor of the circuit you can use the formula: voltage – LED-voltage / LED-current.

The function display_number() sets the ledmask according to each number. So for example to display number 2, we set LED 1,2,4,5,7 to zero and LED1_SWITCH to 1.

You can display numbers by using the char-device. Either by writing ioctl command:  ioctl(fd,DISPLAY_SET, &output) or by writing directly to the char-device like “echo 20 > /dev/LED_display”

Right now im using the display to show the CPU-usage and it works great 🙂

To install the driver you run the load-script LED_display_load, and remove with LED_display_unload.

Get the source-code @ gitub.org

Feel free to ask questions and make comments!

Heatsink arrived to MK802

I bought a MK802 for a couple of weeks ago. It’s a really cool ARM-device that runs Linux. I’ve been running a Lubuntu-distro for a while and it works pretty decent. Of course I miss the hardware acceleration in X, and really holding my thumbs for the Limaproject.
Anyway. The allwinner A10 chip gets really hot! Compared to the TI-AM3359 overclocked to 920Mhz, it is still MUCH warmer. So to spread the heat i got a small heatsinks from Conrad.

The heatsink did the job, so now i’m not worried about heating issues anymore. Over and out!