Saturday, August 8, 2015

Beagle Bone Black GPIO LED control

Hi Folks! Welcome to my Blog. 

I have a sample code to share with you for controlling a LED on your board running Linux. LED ON/OFF is controlled by the CPU GPIO. In this example, I am using BeagleBoneBlack for controlling LED.

In kernel modules it was crude practice to control the LED by controlling its corresponding GPIO, this requires, proper pin-muxing is done and in your module you have to do "requesting for GPIO" --> "make sure it is valid" --> "setting as output" -> "setting gpio value to 0/1" to turn OFF/ON. 

In latest kernel we have "LED Support" CONFIG_LEDS_GPIO under this section we see LEDS_TRIGGERS, TRIGGER_CPU, TRIGGER_GPIO for various purposes. 


On BBB we have 4 user-leds for status, from the  am335x-bone-common.dtsi files we can see that
  • user-led0 --> "heartbeat" this is used by drivers/leds/ledtrig-heartbeat.c to show that sytem is alive
  • user-led1 --> "mmc0" this is used by drivers/mmc/core/host.c in mmc_add_host function
  • user-led2 --> "cpu0" this is use by drivers/leds/ledtrig-cpu.c to show the cpu status
  • user-led3 --> "mmc1" we use this led in our module for experimentation 

Let us assume our device name as "myled", and its obvious that you have your device structure lets say I have the following structure for myled device. You have to make sure you have a member of structure type led_trigger

** Do changes to am335x-bone-common.dtsi  file, rename "mmc1" as "myled" as shown below. Proper pin-muxing is done in the same file for all the four leds.

led3 {
      label = "beaglebone:green:usr3";
      gpios = <&gpio2 24 0>;
      default-state = "off";
      linux,default-trigger = "myled";
};

this is my "myled" device structure with member "led" pointer to led_trigger structure.

struct myled {
    struct device *dev;
    unsigned int id;
#ifdef CONFIG_LEDS_TRIGGERS
    struct led_trigger *led;  /* activity led */
#endif
    char name[8];
}

in the module make sure you include "leds.h"header file.

#include <linux/of_device.h>
#include <linux/sysfs.h>
#include <linux/leds.h>

A pointer to my device structure defined globally, and its memory is allocated in the probe of the module. In the probe you need to register with led_trigger as shown below

struct myled *mdev; //declared globally

led_trigger_register_simple(dev_name(mdev->dev), &mdev->led);


for controlling the led lets use sysfs interface, like reading a file should turn ON the LED and similarly for OFF

static ssize_t my_led_on(struct device *dev, struct device_attribute *attr, char *buf)
{ 
   ssize_t i = 0;
   
   led_trigger_event(mdev->led, LED_FULL);   
   i += sprintf(buf, "LED is ON\n");
   return i;
}
static ssize_t my_led_off(struct device *dev, struct device_attribute *attr, char *buf)
{ 
   ssize_t i = 0;
   
   led_trigger_event(mdev->led, LED_OFF);   
   i += sprintf(buf, "LED is OFF\n");
   return i;
}
static DEVICE_ATTR(myled_on, 0444, my_led_on, NULL);
static DEVICE_ATTR(myled_off, 0444, my_led_off, NULL); 

static const struct attribute_group myled_att_gr = {
    &dev_attr_myled_on.attr,
    &dev_attr_myled_off.attr,
    NULL
}

static const struct attribute_group myled_att_gr = {
    .name = "myled",
    .attrs = myled_att
};


Create sysfs interface in the probe of your module

ret = sysfs_create_group(&mdev->dev.kobj, &myled_att_gr);
if (ret) {
    dev_err(&mdev->dev, "device_create_file failed\n");
    return ret;
}

in the "remove" of your module you have to unregister with led_trigger as shown below


led_trigger_unregister_simple(mdev->led);

This completes the coding part, assuming you are able to compile the code with out error and have booted to shell on BBB with your module loaded. We shall use the sysfs interface created above for controlling the LED. Reading the file "myled_on" will call the function "my_led_on" and turns the LED ON using the led_trigger_event and similarly for turning OFF the led.

If you have any issue booting to shell, check my post Booting BeagleBoneBlack

# cat myled_on
LED is ON
#

use can now see user-led3 is ON

# cat myled_off
LED is OFF
#

use can now see user-led3 is OFF.

This process has simplified the things for controlling the LEDs on your board and reduces the number of lines of code you have to write for controlling the led.

You can play around with these leds, by tweaking into ledtrig-cpu.c &
ledtrig-heartbeat.c by changing the names in am335x-bone-common.dtsi or by adding extra led on P8 or P9 expander of BBB


To understand more internals look at drivers/leds/leds-gpio.c, drivers/gpio/gpiolib-of.c files


 please leave your comments, it will be encouraging :)



Sample code to create sysfs interface in kernel module

Hi Folks! Welcome to my Blog. 

I have a sample code to share with you using sysfs interface in kernel module for controlling a LED on your board running Linux. LED ON/OFF is controlled by the CPU GPIO. In this example, I am using BeagleBoneBlack for controlling LED.

In kernel modules it was crude practice to control the LED by controlling its corresponding GPIO, this requires, proper pin-muxing is done and in your module you have to do "requesting for GPIO" --> "make sure it is valid" --> "setting as output" -> "setting gpio value to 0/1" to turn OFF/ON. 

In latest kernel we have "LED Support" CONFIG_LEDS_GPIO under this section we see LEDS_TRIGGERS, TRIGGER_CPU, TRIGGER_GPIO for various purposes. 


On BBB we have 4 user-leds for status, from the  am335x-bone-common.dtsi files we can see that
  • user-led0 --> "heartbeat" this is used by drivers/leds/ledtrig-heartbeat.c to show that sytem is alive
  • user-led1 --> "mmc0" this is used by drivers/mmc/core/host.c in mmc_add_host function
  • user-led2 --> "cpu0" this is use by drivers/leds/ledtrig-cpu.c to show the cpu status
  • user-led3 --> "mmc1" we use this led in our module for experimentation 

Let us assume our device name as "myled", and its obvious that you have your device structure lets say I have the following structure for myled device. You have to make sure you have a member of structure type led_trigger

** Do changes to am335x-bone-common.dtsi  file, rename "mmc1" as "myled" as shown below. Proper pin-muxing is done in the same file for all the four leds.

led3 {
      label = "beaglebone:green:usr3";
      gpios = <&gpio2 24 0>;
      default-state = "off";
      linux,default-trigger = "myled";
};

this is my "myled" device structure with member "led" pointer to led_trigger structure.

struct myled {
    struct device *dev;
    unsigned int id;
#ifdef CONFIG_LEDS_TRIGGERS
    struct led_trigger *led;  /* activity led */
#endif
    char name[8];
}

in the module make sure you include "leds.h"header file.

#include <linux/of_device.h>
#include <linux/sysfs.h>
#include <linux/leds.h>

A pointer to my device structure defined globally, and its memory is allocated in the probe of the module. In the probe you need to register with led_trigger as shown below

struct myled *mdev; //declared globally

led_trigger_register_simple(dev_name(mdev->dev), &mdev->led);


for controlling the led lets use sysfs interface, like reading a file should turn ON the LED and similarly for OFF

static ssize_t my_led_on(struct device *dev, struct device_attribute *attr, char *buf)
{ 
   ssize_t i = 0;
   
   led_trigger_event(mdev->led, LED_FULL);   
   i += sprintf(buf, "LED is ON\n");
   return i;
}
static ssize_t my_led_off(struct device *dev, struct device_attribute *attr, char *buf)
{ 
   ssize_t i = 0;
   
   led_trigger_event(mdev->led, LED_OFF);   
   i += sprintf(buf, "LED is OFF\n");
   return i;
}
static DEVICE_ATTR(myled_on, 0444, my_led_on, NULL);
static DEVICE_ATTR(myled_off, 0444, my_led_off, NULL); 

static const struct attribute_group myled_att_gr = {
    &dev_attr_myled_on.attr,
    &dev_attr_myled_off.attr,
    NULL
}

static const struct attribute_group myled_att_gr = {
    .name = "myled",
    .attrs = myled_att
};


Create sysfs interface in the probe of your module

ret = sysfs_create_group(&mdev->dev.kobj, &myled_att_gr);
if (ret) {
    dev_err(&mdev->dev, "device_create_file failed\n");
    return ret;
}

in the "remove" of your module you have to unregister with led_trigger as shown below


led_trigger_unregister_simple(mdev->led);

This completes the coding part, assuming you are able to compile the code with out error and have booted to shell on BBB with your module loaded. We shall use the sysfs interface created above for controlling the LED. Reading the file "myled_on" will call the function "my_led_on" and turns the LED ON using the led_trigger_event and similarly for turning OFF the led.

# cat myled_on
LED is ON
#

use can now see user-led3 is ON

# cat myled_off
LED is OFF
#

use can now see user-led3 is OFF.

This process has simplified the things for controlling the LEDs on your board and reduces the number of lines of code you have to write for controlling the led.

You can play around with these leds, by tweaking into ledtrig-cpu.c &
ledtrig-heartbeat.c by changing the names in am335x-bone-common.dtsi or by adding extra led on P8 or P9 expander of BBB


To understand more internals look at drivers/leds/leds-gpio.c, drivers/gpio/gpiolib-of.c files


 please leave your comments, it will be encouraging :)


Controling GPIO LED in Linux kernel

Hi Folks! Welcome to my Blog. 

I have a sample code to share with you for controlling a LED on your board running Linux. LED ON/OFF is controlled by the CPU GPIO. In this example, I am using BeagleBoneBlack for controlling LED.

In kernel modules it was crude practice to control the LED by controlling its corresponding GPIO, this requires, proper pin-muxing is done and in your module you have to do "requesting for GPIO" --> "make sure it is valid" --> "setting as output" -> "setting gpio value to 0/1" to turn OFF/ON. 

In latest kernel we have "LED Support" CONFIG_LEDS_GPIO under this section we see LEDS_TRIGGERS, TRIGGER_CPU, TRIGGER_GPIO for various purposes. 


On BBB we have 4 user-leds for status, from the  am335x-bone-common.dtsi files we can see that
  • user-led0 --> "heartbeat" this is used by drivers/leds/ledtrig-heartbeat.c to show that sytem is alive
  • user-led1 --> "mmc0" this is used by drivers/mmc/core/host.c in mmc_add_host function
  • user-led2 --> "cpu0" this is use by drivers/leds/ledtrig-cpu.c to show the cpu status
  • user-led3 --> "mmc1" we use this led in our module for experimentation 

Let us assume our device name as "myled", and its obvious that you have your device structure lets say I have the following structure for myled device. You have to make sure you have a member of structure type led_trigger

** Do changes to am335x-bone-common.dtsi  file, rename "mmc1" as "myled" as shown below. Proper pin-muxing is done in the same file for all the four leds.

led3 {
      label = "beaglebone:green:usr3";
      gpios = <&gpio2 24 0>;
      default-state = "off";
      linux,default-trigger = "myled";
};

this is my "myled" device structure with member "led" pointer to led_trigger structure.

struct myled {
    struct device *dev;
    unsigned int id;
#ifdef CONFIG_LEDS_TRIGGERS
    struct led_trigger *led;  /* activity led */
#endif
    char name[8];
}

in the module make sure you include "leds.h"header file.

#include <linux/of_device.h>
#include <linux/sysfs.h>
#include <linux/leds.h>

A pointer to my device structure defined globally, and its memory is allocated in the probe of the module. In the probe you need to register with led_trigger as shown below

struct myled *mdev; //declared globally

led_trigger_register_simple(dev_name(mdev->dev), &mdev->led);


for controlling the led lets use sysfs interface, like reading a file should turn ON the LED and similarly for OFF

static ssize_t my_led_on(struct device *dev, struct device_attribute *attr, char *buf)
{ 
   ssize_t i = 0;
   
   led_trigger_event(mdev->led, LED_FULL);   
   i += sprintf(buf, "LED is ON\n");
   return i;
}
static ssize_t my_led_off(struct device *dev, struct device_attribute *attr, char *buf)
{ 
   ssize_t i = 0;
   
   led_trigger_event(mdev->led, LED_OFF);   
   i += sprintf(buf, "LED is OFF\n");
   return i;
}
static DEVICE_ATTR(myled_on, 0444, my_led_on, NULL);
static DEVICE_ATTR(myled_off, 0444, my_led_off, NULL); 

static const struct attribute_group myled_att_gr = {
    &dev_attr_myled_on.attr,
    &dev_attr_myled_off.attr,
    NULL
}

static const struct attribute_group myled_att_gr = {
    .name = "myled",
    .attrs = myled_att
};


Create sysfs interface in the probe of your module

ret = sysfs_create_group(&mdev->dev.kobj, &myled_att_gr);
if (ret) {
    dev_err(&mdev->dev, "device_create_file failed\n");
    return ret;
}

in the "remove" of your module you have to unregister with led_trigger as shown below


led_trigger_unregister_simple(mdev->led);

This completes the coding part, assuming you are able to compile the code with out error and have booted to shell on BBB with your module loaded. We shall use the sysfs interface created above for controlling the LED. Reading the file "myled_on" will call the function "my_led_on" and turns the LED ON using the led_trigger_event and similarly for turning OFF the led.

# cat myled_on
LED is ON
#

use can now see user-led3 is ON

# cat myled_off
LED is OFF
#

use can now see user-led3 is OFF.

This process has simplified the things for controlling the LEDs on your board and reduces the number of lines of code you have to write for controlling the led.

You can play around with these leds, by tweaking into ledtrig-cpu.c &
ledtrig-heartbeat.c by changing the names in am335x-bone-common.dtsi or by adding extra led on P8 or P9 expander of BBB


To understand more internals look at drivers/leds/leds-gpio.c, drivers/gpio/gpiolib-of.c files


 please leave your comments, it will be encouraging :)



Module to use LED Support & LEDS_TRIGGER_GPIO in Linux kernel


Hi Folks! Welcome to my Blog. 

I have a sample code to share with you for controlling a LED on your board running Linux. LED ON/OFF is controlled by the CPU GPIO. In this example, I am using BeagleBoneBlack for controlling LED.

In kernel modules it was crude practice to control the LED by controlling its corresponding GPIO, this requires, proper pin-muxing is done and in your module you have to do "requesting for GPIO" --> "make sure it is valid" --> "setting as output" -> "setting gpio value to 0/1" to turn OFF/ON. 

In latest kernel we have "LED Support" CONFIG_LEDS_GPIO under this section we see LEDS_TRIGGERS, TRIGGER_CPU, TRIGGER_GPIO for various purposes. 


On BBB we have 4 user-leds for status, from the  am335x-bone-common.dtsi files we can see that
  • user-led0 --> "heartbeat" this is used by drivers/leds/ledtrig-heartbeat.c to show that sytem is alive
  • user-led1 --> "mmc0" this is used by drivers/mmc/core/host.c in mmc_add_host function
  • user-led2 --> "cpu0" this is use by drivers/leds/ledtrig-cpu.c to show the cpu status
  • user-led3 --> "mmc1" we use this led in our module for experimentation 

Let us assume our device name as "myled", and its obvious that you have your device structure lets say I have the following structure for myled device. You have to make sure you have a member of structure type led_trigger

** Do changes to am335x-bone-common.dtsi  file, rename "mmc1" as "myled" as shown below. Proper pin-muxing is done in the same file for all the four leds.

led3 {
      label = "beaglebone:green:usr3";
      gpios = <&gpio2 24 0>;
      default-state = "off";
      linux,default-trigger = "myled";
};

this is my "myled" device structure with member "led" pointer to led_trigger structure.

struct myled {
    struct device *dev;
    unsigned int id;
#ifdef CONFIG_LEDS_TRIGGERS
    struct led_trigger *led;  /* activity led */
#endif
    char name[8];
}

in the module make sure you include "leds.h"header file.

#include <linux/of_device.h>
#include <linux/sysfs.h>
#include <linux/leds.h>

A pointer to my device structure defined globally, and its memory is allocated in the probe of the module. In the probe you need to register with led_trigger as shown below

struct myled *mdev; //declared globally

led_trigger_register_simple(dev_name(mdev->dev), &mdev->led);


for controlling the led lets use sysfs interface, like reading a file should turn ON the LED and similarly for OFF

static ssize_t my_led_on(struct device *dev, struct device_attribute *attr, char *buf)
{ 
   ssize_t i = 0;
   
   led_trigger_event(mdev->led, LED_FULL);   
   i += sprintf(buf, "LED is ON\n");
   return i;
}
static ssize_t my_led_off(struct device *dev, struct device_attribute *attr, char *buf)
{ 
   ssize_t i = 0;
   
   led_trigger_event(mdev->led, LED_OFF);   
   i += sprintf(buf, "LED is OFF\n");
   return i;
}
static DEVICE_ATTR(myled_on, 0444, my_led_on, NULL);
static DEVICE_ATTR(myled_off, 0444, my_led_off, NULL); 

static const struct attribute_group myled_att_gr = {
    &dev_attr_myled_on.attr,
    &dev_attr_myled_off.attr,
    NULL
}

static const struct attribute_group myled_att_gr = {
    .name = "myled",
    .attrs = myled_att
};


Create sysfs interface in the probe of your module

ret = sysfs_create_group(&mdev->dev.kobj, &myled_att_gr);
if (ret) {
    dev_err(&mdev->dev, "device_create_file failed\n");
    return ret;
}

in the "remove" of your module you have to unregister with led_trigger as shown below


led_trigger_unregister_simple(mdev->led);

This completes the coding part, assuming you are able to compile the code with out error and have booted to shell on BBB with your module loaded. We shall use the sysfs interface created above for controlling the LED. Reading the file "myled_on" will call the function "my_led_on" and turns the LED ON using the led_trigger_event and similarly for turning OFF the led.

If you have any issue booting to shell, check my post Booting BeagleBoneBlack

# cat myled_on
LED is ON
#




use can now see user-led3 is ON

# cat myled_off
LED is OFF
#

use can now see user-led3 is OFF.

This process has simplified the things for controlling the LEDs on your board and reduces the number of lines of code you have to write for controlling the led.

You can play around with these leds, by tweaking into ledtrig-cpu.c &
ledtrig-heartbeat.c by changing the names in am335x-bone-common.dtsi or by adding extra led on P8 or P9 expander of BBB


To understand more internals look at drivers/leds/leds-gpio.c, drivers/gpio/gpiolib-of.c files


 please leave your comments, it will be encouraging :)

Thursday, August 6, 2015

Beagle Bone Black and serial

Hi Foks.! Welcome to my blog.

Yes, we are going to boot BBB (Beagle Bone Black) over UART, seems strange..? even I had the same opinion, but its importance is really know when you work on a new board bring up task. UART interface is very reliable and easy to configure, hence I prefer this as the best option as boot media/interface during bring up time, later we can verify other boot mechanism like boot from SPI/NAND/MMC.

Once we are at U-boot prompt we are almost done, we can chose how we want to load the kernel image and from the command line arguments we save the about file system and other extra env settings. 

To get started we need the following:
  • BeagleBoneBlack (BBB) board
  • Linux distribution based host machine ( I have Ubuntu 14.04)
  • CP2102 USB2.0 to TTL UART serial converter module.
  • 100-240V to 5V-1.0 or 2.0A  adapter/converter.
Serial Connection:

Locate the 6-pin header on BBB, written as "J1" below the first pin on the PCB as show in the below picture.

 
  • J1 = GND (Ground)
  • J4 = RXD (Receive Data)
  • J5 = TXD (Transmit Data)

CP2102 USB2.0 to TTL UART serial converter

Connect J4 (RXD) to TXD line of  CP2102 USB2.0 to TTL UART serial converter
Connect J5 (TXD) to RXD line of  CP2102 USB2.0 to TTL UART serial converter
Connect J1 (GND) to GND line of  CP2102 USB2.0 to TTL UART serial converter

This makes the serial console setup ready.


Download U-Boot Source :

gvk51@gvk:~$ mkdir src
gvk51@gvk:~$ cd src
gvk51@gvk:~/src$ git clone git://git.denx.de/u-boot.git


Initialize Build Environment : 

gvk51@gvk:~$ sudo apt-get install git u-boot-tools g++ gawk lzop texinfo git-core build-essential libncurses5-dev gcc-arm-linux-gnueabi

Install all the mentioned packages for making build smooth.
 


Building the Source:

After successful installation of packages we now start building the u-boot source, for use to boot from UART we need the following images u-boot-spl.bin & u-boot.img

gvk51@gvk:~/src$ mkdir images
gvk51@gvk:~/src$ u-boot
gvk51@gvk:~/src/u-boot$ make am335x_boneblack_defconfig
gvk51@gvk:~/src/u-boot$ make -j4
gvk51@gvk:~/src/u-boot$ cp ./u-boot.img ../images/
gvk51@gvk:~/src/u-boot$ cp ./spl/u-boot-spl.bin ../images/

Booting BBB from UART:

BBB has different boots modes like boot from eMMC, uSD, serial & usb. To change the boot mode there is a switch S2, holding the boot switch down during boot without a uSD card inserted will force the boot source to be the USB port and if nothing is detected on the USB client port, it will go to the serial port for download.

Host tools for UART boot:

I have used picocom host tool to boot from serial, install it as shown below

gvk51@gvk:~$ sudo apt-get install picocom lrzsz

cd to directory where we have copied images, that is src/images folder. Assuming you have connected serial-to-usb converter, then you see a device node say /dev/ttyUSB0 on your host machine. Launch picocom from the images folder.

Commands for picocom:
  • sending a file: press Ctrl+a and then press Ctrl+s
  • exit: Ctrl+a and then press Ctrl+x
Step1: Open a terminal, issue command picocom -b 115200 /dev/ttyUSB0 --send-cmd "sx -vv", you will see the following output on the console.

picocom v1.7

port is            : /dev/ttyUSB0
flowcontrol     : none
baudrate is     : 115200
parity is          : none
databits are    : 8
escape is         : C-a
local echo is    : no
noinit is          : no
noreset is        : no
nolock is         : no
send_cmd is     : sx -vv
receive_cmd is : rz -vv
imap is            :
omap is           :
emap is           : crcrlf,delbs,

Terminal ready
Step2: give key-combination ctrl+A (ctrl+shift+a), then you will see

*** file:
enter the file name u-boot-spl.bin and hit enter, you will see 

sx -vv u-boot-spl.bin
Sending u-boot-spl.bin, 570 blocks: Give your local XMODEM receive command now.

 

Step3: Now holding the boot-mode switch apply power to BBB (Use 5V-1Amp power supply), make sure there is no uSD & no USB cable connected to BBB. picocom starts sending the first stage boot-loader u-boot-spl.bin over UART, you will see the following output, after successful transfer you will see the character 'C' as acknowledgement from BBB.
 
Xmodem sectors/kbytes sent:   0/ 0kRetry 0: Timeout on sector ACK
Retry 0: Timeout on sector ACK
Retry 0: Got 00 for sector ACK
Retry 0: NAK on sector
Bytes Sent:  73088   BPS:304                            

Transfer complete

*** exit status: 0

U-Boot SPL 2015.07-00256-g413978d-dirty (Aug 06 2015 - 11:52:06)
C

Step4:  After you see the acknowledgement give key combination ctrl+A (ctrl+shift+a) to send the u-boot.img.

*** file:
enter the file name u-boot.img and hit enter, here you need to be patient, transfer of u-boot takes around 2-3 minutes and after successful you don't see any acknowledgement 'C' from BBB, after that wait for another 1-2 minutes to see BBB restarting and halt it at u-boot prompt by pressing a key, you will see the below log.

*** file: u-boot.img
sx -vv u-boot.img
Sending u-boot.img, 3239 blocks: Give your local XMODEM receive command now.
Xmodem sectors/kbytes sent:   0/ 0kRetry 0: NAK on sector
Bytes Sent: 414720   BPS:4480                           

Transfer complete

*** exit status: 0
xyzModem - CRC mode, 3241(SOH)/0(STX)/0(CAN) packets, 3 retries
Loaded 414700 bytes

U-Boot 2015.07-00256-g413978d-dirty (Aug 06 2015 - 11:52:06 +0530)

       Watchdog enabled
I2C:   ready
DRAM:  512 MiB
MMC:   OMAP SD/MMC: 0
Card did not respond to voltage select!
MMC init failedNet:   <ethaddr> not set. Validating first E-fuse MAC
cpsw, usb_ether
Hit any key to stop autoboot:  0
U-Boot# 

Here is the complete log of the boot sequence.

picocom -b 115200 /dev/ttyUSB0 --send-cmd "sx -vv"
picocom v1.7

port is        : /dev/ttyUSB0
flowcontrol    : none
baudrate is    : 115200
parity is      : none
databits are   : 8
escape is      : C-a
local echo is  : no
noinit is      : no
noreset is     : no
nolock is      : no
send_cmd is    : sx -vv
receive_cmd is : rz -vv
imap is        : 
omap is        : 
emap is        : crcrlf,delbs,

Terminal ready

*** file: u-boot-spl.bin
sx -vv u-boot-spl.bin 
Sending u-boot-spl.bin, 570 blocks: Give your local XMODEM receive command now.
Bytes Sent:  73088   BPS:6471                            

Transfer complete

*** exit status: 0

U-Boot SPL 2015.07-00256-g413978d-dirty (Aug 06 2015 - 11:52:06)
C
*** file: u-boot.img
sx -vv u-boot.img 
Sending u-boot.img, 3239 blocks: Give your local XMODEM receive command now.
Xmodem sectors/kbytes sent:   0/ 0kRetry 0: NAK on sector
Bytes Sent: 414720   BPS:4480                            

Transfer complete

*** exit status: 0
 xyzModem - CRC mode, 3241(SOH)/0(STX)/0(CAN) packets, 3 retries
Loaded 414700 bytes


U-Boot 2015.07-00256-g413978d-dirty (Aug 06 2015 - 11:52:06 +0530)

       Watchdog enabled
I2C:   ready
DRAM:  512 MiB
MMC:   OMAP SD/MMC: 0
Card did not respond to voltage select!
MMC init failedNet:   <ethaddr> not set. Validating first E-fuse MAC
cpsw, usb_ether
Hit any key to stop autoboot:  0 
U-Boot# 


from u-boot its always up to you from where you load the kernel and filesystem.


To boot BBB with Network File System click this link: BBB booting with NFS

Please leave your comments, it will be encouraging :) 




Booting BeagleBoneBlack over serial

Hi Foks.! Welcome to my blog.

Yes, we are going to boot BBB (Beagle Bone Black) over UART, seems strange..? even I had the same opinion, but its importance is really know when you work on a new board bring up task. UART interface is very reliable and easy to configure, hence I prefer this as the best option as boot media/interface during bring up time, later we can verify other boot mechanism like boot from SPI/NAND/MMC.

Once we are at U-boot prompt we are almost done, we can chose how we want to load the kernel image and from the command line arguments we save the about file system and other extra env settings. 

To get started we need the following:
  • BeagleBoneBlack (BBB) board
  • Linux distribution based host machine ( I have Ubuntu 14.04)
  • CP2102 USB2.0 to TTL UART serial converter module.
  • 100-240V to 5V-1.0 or 2.0A  adapter/converter.
Serial Connection:

Locate the 6-pin header on BBB, written as "J1" below the first pin on the PCB as show in the below picture.

 
  • J1 = GND (Ground)
  • J4 = RXD (Receive Data)
  • J5 = TXD (Transmit Data)

CP2102 USB2.0 to TTL UART serial converter

Connect J4 (RXD) to TXD line of  CP2102 USB2.0 to TTL UART serial converter
Connect J5 (TXD) to RXD line of  CP2102 USB2.0 to TTL UART serial converter
Connect J1 (GND) to GND line of  CP2102 USB2.0 to TTL UART serial converter

This makes the serial console setup ready.


Download U-Boot Source :

gvk51@gvk:~$ mkdir src
gvk51@gvk:~$ cd src
gvk51@gvk:~/src$ git clone git://git.denx.de/u-boot.git


Initialize Build Environment : 

gvk51@gvk:~$ sudo apt-get install git u-boot-tools g++ gawk lzop texinfo git-core build-essential libncurses5-dev gcc-arm-linux-gnueabi

Install all the mentioned packages for making build smooth.
 


Building the Source:

After successful installation of packages we now start building the u-boot source, for use to boot from UART we need the following images u-boot-spl.bin & u-boot.img

gvk51@gvk:~/src$ mkdir images
gvk51@gvk:~/src$ u-boot
gvk51@gvk:~/src/u-boot$ make am335x_boneblack_defconfig
gvk51@gvk:~/src/u-boot$ make -j4
gvk51@gvk:~/src/u-boot$ cp ./u-boot.img ../images/
gvk51@gvk:~/src/u-boot$ cp ./spl/u-boot-spl.bin ../images/

Booting BBB from UART:

BBB has different boots modes like boot from eMMC, uSD, serial & usb. To change the boot mode there is a switch S2, holding the boot switch down during boot without a uSD card inserted will force the boot source to be the USB port and if nothing is detected on the USB client port, it will go to the serial port for download.

Host tools for UART boot:

I have used picocom host tool to boot from serial, install it as shown below

gvk51@gvk:~$ sudo apt-get install picocom lrzsz

cd to directory where we have copied images, that is src/images folder. Assuming you have connected serial-to-usb converter, then you see a device node say /dev/ttyUSB0 on your host machine. Launch picocom from the images folder.

Commands for picocom:
  • sending a file: press Ctrl+a and then press Ctrl+s
  • exit: Ctrl+a and then press Ctrl+x
Step1: Open a terminal, issue command picocom -b 115200 /dev/ttyUSB0 --send-cmd "sx -vv", you will see the following output on the console.

picocom v1.7

port is            : /dev/ttyUSB0
flowcontrol     : none
baudrate is     : 115200
parity is          : none
databits are    : 8
escape is         : C-a
local echo is    : no
noinit is          : no
noreset is        : no
nolock is         : no
send_cmd is     : sx -vv
receive_cmd is : rz -vv
imap is            :
omap is           :
emap is           : crcrlf,delbs,

Terminal ready
Step2: give key-combination ctrl+A (ctrl+shift+a), then you will see

*** file:
enter the file name u-boot-spl.bin and hit enter, you will see 

sx -vv u-boot-spl.bin
Sending u-boot-spl.bin, 570 blocks: Give your local XMODEM receive command now.

 

Step3: Now holding the boot-mode switch apply power to BBB, (Use 5V-1Amp power supply), make sure there is no uSD & no USB cable connected to BBB. picocom starts sending the first stage boot-loader u-boot-spl.bin over UART, you will see the following output, after successful transfer you will see the character 'C' as acknowledgement from BBB.
 
Xmodem sectors/kbytes sent:   0/ 0kRetry 0: Timeout on sector ACK
Retry 0: Timeout on sector ACK
Retry 0: Got 00 for sector ACK
Retry 0: NAK on sector
Bytes Sent:  73088   BPS:304                            

Transfer complete

*** exit status: 0

U-Boot SPL 2015.07-00256-g413978d-dirty (Aug 06 2015 - 11:52:06)
C

Step4:  After you see the acknowledgement give key combination ctrl+A (ctrl+shift+a) to send the u-boot.img.

*** file:
enter the file name u-boot.img and hit enter, here you need to be patient, transfer of u-boot takes around 2-3 minutes and after successful you don't see any acknowledgement 'C' from BBB, after that wait for another 1-2 minutes to see BBB restarting and halt it at u-boot prompt by pressing a key, you will see the below log.

*** file: u-boot.img
sx -vv u-boot.img
Sending u-boot.img, 3239 blocks: Give your local XMODEM receive command now.
Xmodem sectors/kbytes sent:   0/ 0kRetry 0: NAK on sector
Bytes Sent: 414720   BPS:4480                           

Transfer complete

*** exit status: 0
xyzModem - CRC mode, 3241(SOH)/0(STX)/0(CAN) packets, 3 retries
Loaded 414700 bytes

U-Boot 2015.07-00256-g413978d-dirty (Aug 06 2015 - 11:52:06 +0530)

       Watchdog enabled
I2C:   ready
DRAM:  512 MiB
MMC:   OMAP SD/MMC: 0
Card did not respond to voltage select!
MMC init failedNet:   <ethaddr> not set. Validating first E-fuse MAC
cpsw, usb_ether
Hit any key to stop autoboot:  0
U-Boot# 

Here is the complete log of the boot sequence.

picocom -b 115200 /dev/ttyUSB0 --send-cmd "sx -vv"
picocom v1.7

port is        : /dev/ttyUSB0
flowcontrol    : none
baudrate is    : 115200
parity is      : none
databits are   : 8
escape is      : C-a
local echo is  : no
noinit is      : no
noreset is     : no
nolock is      : no
send_cmd is    : sx -vv
receive_cmd is : rz -vv
imap is        : 
omap is        : 
emap is        : crcrlf,delbs,

Terminal ready

*** file: u-boot-spl.bin
sx -vv u-boot-spl.bin 
Sending u-boot-spl.bin, 570 blocks: Give your local XMODEM receive command now.
Bytes Sent:  73088   BPS:6471                            

Transfer complete

*** exit status: 0

U-Boot SPL 2015.07-00256-g413978d-dirty (Aug 06 2015 - 11:52:06)
C
*** file: u-boot.img
sx -vv u-boot.img 
Sending u-boot.img, 3239 blocks: Give your local XMODEM receive command now.
Xmodem sectors/kbytes sent:   0/ 0kRetry 0: NAK on sector
Bytes Sent: 414720   BPS:4480                            

Transfer complete

*** exit status: 0
 xyzModem - CRC mode, 3241(SOH)/0(STX)/0(CAN) packets, 3 retries
Loaded 414700 bytes


U-Boot 2015.07-00256-g413978d-dirty (Aug 06 2015 - 11:52:06 +0530)

       Watchdog enabled
I2C:   ready
DRAM:  512 MiB
MMC:   OMAP SD/MMC: 0
Card did not respond to voltage select!
MMC init failedNet:   <ethaddr> not set. Validating first E-fuse MAC
cpsw, usb_ether
Hit any key to stop autoboot:  0 
U-Boot# 


from u-boot its always up to you from where you load the kernel and filesystem.


To boot BBB with Network File System click this link: BBB booting with NFS

Please leave your comments, it will be encouraging :) 




Boot BeagleBone black with NFS

Hi Foks.! Welcome to my blog.

To make this happen I have been through many blogs, some where help-full, out of my experimentation  here are the steps to boot kernel with NFS. This procedure is applicable to any board that can boot till u-boot prompt. I am using Beagle Bone Black as an example.

To get started we need the following:
  • BeagleBoneBlack (BBB) board
  • Linux distribution based host machine ( I have Ubuntu 14.04)
  • CP2102 USB2.0 to TTL UART serial converter module.
  • Ethernet cable
  • 100-240V to 5V-1.0 or 2.0A  adapter/converter
  • TFTP & NFS server 
  • kernel & buildroot source
  • I am using filesystem generated from buildroot
Serial Connection:

Locate the 6-pin header on BBB, written as "J1" below the first pin on the PCB as show in the below picture.

 
  • J1 = GND (Ground)
  • J4 = RXD (Receive Data)
  • J5 = TXD (Transmit Data)

CP2102 USB2.0 to TTL UART serial converter

Connect J4 (RXD) to TXD line of  CP2102 USB2.0 to TTL UART serial converter
Connect J5 (TXD) to RXD line of  CP2102 USB2.0 to TTL UART serial converter
Connect J1 (GND) to GND line of  CP2102 USB2.0 to TTL UART serial converter

This makes the serial console setup ready.

Initialize Build Environment : 

gvk51@gvk:~$ sudo apt-get install git u-boot-tools g++ gawk lzop texinfo git-core build-essential libncurses5-dev gcc-arm-linux-gnueabi

Install all the mentioned packages for making build smooth.

Download Kernel Source :

gvk51@gvk:~$ cd src
gvk51@gvk:~/src$ git clone git://github.com/beagleboard/kernel.git
gvk51@gvk:~/src$ cd kernel
gvk51@gvk:~/src/kernle$ git checkout 3.8
gvk51@gvk:~/src/kernle$ ./patch.sh
gvk51@gvk:~/src/kernle$ cp configs/beaglebone kernel/arch/arm/configs/beaglebone_defconfig
gvk51@gvk:~/src/kernle$ wget http://arago-project.org/git/projects/?p=am33x-cm3.git\;a=blob_plain\;f=bin/am335x-pm-firmware.bin\;hb=HEAD -O kernel/firmware/am335x-pm-firmware.bin

Download Buildroot Source :

gvk51@gvk:~$ cd src
gvk51@gvk:~$ git clone git://git.buildroot.net/buildroot

Download the buildroot config from the below link, it is built for ARM-little endian-cortex-A8 choosing 3.8.13 kernel version headers, and build the cross compiler toolchain by itself, copy nfs_defconfing file to buildroot/configs folder

From buildroot disable the udhcp network utility of the busy-box, other wise while booting it tries to get a dynamic IP address causing the nfs failure. below are the steps to disable.

$ cd src/buildroot
$ make busybox-menuconfig

Goto "Networking Utilities  --->" & disable the following
  • udhcp client for DHCPv6 (udhcpc6) 
  • udhcp server (udhcpd)
  • udhcp client (udhcpc) 
save & eixt
$ make busybox-update-config

Click to Download buildroot Config file nfs_defconfig

Building kernel & buildroot from source:

Assuming build environment is successfully done, we now start building the kernel & buildroot root file-system from source.

gvk51@gvk:~/src$ mkdir images
gvk51@gvk:~/src$ mkdir logs
gvk51@gvk:~/src$ cd kernel/kernel
gvk51@gvk:~/src/kernel/kernel$ make beaglebone_defconfig
gvk51@gvk:~/src/kernel/kernel$ make -j4 uImage dtbs 2>&1 | tee ~/src/logs/kernel.txt
gvk51@gvk:~/src/kernel/kernel$ make -j4 modules
gvk51@gvk:~/src/kernel/kernel$ make uImage-dtb.am335x-boneblack
gvk51@gvk:~/src/kernel/kernel$ cp ./arch/arm/boot/uImage-dtb.am335x-boneblack ~/src/images
gvk51@gvk:~/src/kernel/kernel$ cd ~/src/buildroot
gvk51@gvk:~/src/buildroot$ make nfs_defconfig 
gvk51@gvk:~/src/buildroot$ make 2>&1 | tee ~/src/logs/fs.txt
gvk51@gvk:~/src/buildroot$ cp ./output/images/rootfs.tar.gz ~/src/images

This completes the kernel & build root building, important files we need here are uImage-dtb.am335x-boneblack & rootfs.tar.gz
I assume that you have booted to u-boot prompt on BBB, the boot media can be either uSD or eMMC or UART. For booting from UART, check the link BBB booting from UART

Here we download the kernel image from tftp & rootfs is over the network.


Installing TFTP server on u-buntu:

To install the tftpd package, run the following: 

gvk51@gvk:~$ sudo apt-get install tftpd

To configure the TFTP server, create /etc/xinetd.d/tftp with the following contents: 

service tftp
{
protocol        = udp
port            = 69
socket_type     = dgram
wait            = yes
user            = nobody
server          = /usr/sbin/in.tftpd
server_args     = /tftpboot
disable         = no
}

Run the following to create the TFTP server's base directory and allow anyone to access it:

gvk51@gvk:~# sudo mkdir /tftpboot
gvk51@gvk:~# sudo chmod -R 777 tftpboot
gvk51@gvk:~# sudo chown -R nobody /tftpboot

copy the uImage-dtb.am335x-boneblack to /tftpboot

gvk51@gvk:~$ cp ~/src/images/uImage-dtb.am335x-boneblack

Restart xinetd deamon to enable the server:

gvk51@gvk:~$ sudo /etc/init.d/xinetd restart


Installing NFS services & Tools:

On Ubuntu, Debian, and similar systems, the services and tools required by an NFS server can be installed with the following command:

gvk51@gvk:~$ sudo apt-get install nfs-kernel-server nfs-common portmap

setup the network file system

gvk51@gvk:~# sudo mkdir /srv/nfs/bbb
gvk51@gvk:~# sudo tar -C /srv/nfs/bbb -xzf ~/src/images/rootfs.tar.gz
gvk51@gvk:~# cd /srv/nfs/bbb
gvk51@gvk:/srv/nfs/bb# sudo ln -s bin/busybox init

Add the below line to /etc/exports file, assuming BBB is having a static IP say 192.168.19.112

/srv/nfs/bbb 192.168.19.112(rw,sync,no_root_squash,no_subtree_check)

gvk51@gvk:~# sudo gedit /etc/exports

export the NFS directories and restart the service

gvk51@gvk:~# sudo exportfs -a
gvk51@gvk:~# sudo exportfs -rv
gvk51@gvk:~# sudo service nfs-kernel-server start

 for more details about tftp, nfs  check these links LINK1 LINK2 LINK3

Assuming you are at the u-boot prompt.

IP address of the Ubuntu host machine running tftp & nfs is 192.168.19.144

Hit any key to stop autoboot:  0
U-Boot#
U-Boot# setenv ipaddr 192.168.19.112
U-Boot# ping 192.168.19.144
link up on port 0, speed 100, full duplex
Using cpsw device
host 192.168.19.144 is alive
U-Boot# setenv serverip 192.168.19.144
U-Boot# tftpboot ${kloadaddr} uImage-dtb.am335x-boneblack
link up on port 0, speed 100, full duplex
Using cpsw device
TFTP from server 192.168.19.144; our IP address is 192.168.19.112
Filename 'uImage-dtb.'.
Load address: 0x82000000
Loading: #################################################################
     #################################################################
     #################################################################
     #################################################################
     #################################################################
     #################################################################
     #################################################################
     #################################################################
     #################################################################
     #################################################################
     #################################################################
     #################################################################
     #################################################################
     ###########
     911.1 KiB/s
done
Bytes transferred = 4382407 (42dec7 hex)
U-Boot# setenv bootargs console=ttyO0,115200n8 root=/dev/nfs rw nfsroot=192.168.19.144:/srv/nfs/bbb/,nolock, wsize=1024, rsize=1024 rootwait init=/linuxrc rootdelay=5 ip=192.168.19.112
U-Boot# bootm ${kloadaddr}
## Booting kernel from Legacy Image at 82000000 ...
   Image Name:   Linux-3.8.13-00770-gc0eeacb-dirt
   Created:      2015-08-06   6:27:40 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    4382343 Bytes = 4.2 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
[    0.000000] Booting Linux on physical CPU 0x0
.
.
.
.
[    9.742832] Freeing init memory: 216K
Starting logging: OK
Initializing random number generator... done.
Starting network...
ifup: applet not found
Starting dropbear sshd: OK

Welcome to Buildroot over NFS
root login:

Click to Download BBB NFS Kernel Boot Log

Please leave your comments, that will be encouraging :)