Project Directory Structure
Key project directories for STM32MP157 development:
- Buildroot root filesystem:
/home/developer/projects/stm32mp157/rootfs - NFS root fliesystem:
/home/developer/projects/nfs/rootfs - Linux source code:
/home/developer/projects/linux-5.4.31 - Device tree:
/home/developer/projects/linux-5.4.31/arch/arm/boot/dts/stm32mp157-atk.dts - TFTP server:
/home/developer/projects/tftpboot
Network Booting with U-Boot
To boot Linux using TFTP and NFS:
- Place
uImageandstm32mp157-atk.dtbin/home/developer/projects/tftpboot - Configure network settings on host:
sudo ifconfig eth0 192.168.1.100
- Set U-Boot environment variables:
setenv ipaddr 192.168.1.101
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.100
saveenv
- Download and boot:
tftp 0xc2000000 uImage
tftp 0xc4000000 stm32mp157-atk.dtb
setenv bootargs 'console=ttySTM0,115200 root=/dev/nfs nfsroot=192.168.1.100:/home/developer/projects/nfs/rootfs,proto=tcp rw ip=192.168.1.101:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off'
boot
Character Device Driver API Reference
Key header files and structures for character device drivers:
#include <linux/types.h>
dev_t; // Device number type
int MAJOR(dev_t dev);
int MINOR(dev_t dev);
dev_t MKDEV(unsigned int major, unsigned int minor);
#include <linux/fs.h>
int register_chrdev_region(dev_t first, unsigned int count, char *name);
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
void unregister_chrdev_region(dev_t first, unsigned int count);
struct file_operations {
struct module *owner;
ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
int (*open)(struct inode *, struct file *);
int (*release)(struct inode *, struct file *);
};
#include <linux/cdev.h>
struct cdev *cdev_alloc(void);
void cdev_init(struct cdev *dev, struct file_operations *fops);
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
void cdev_del(struct cdev *dev);
Network Configuration for Development
Configure host for NFS and TFTP:
- Install required packages:
sudo apt-get install nfs-kernel-server tftpd-hpa xinetd
- Create NFS directory:
mkdir -p /home/developer/projects/nfs/rootfs
chmod 777 /home/developer/projects/nfs/rootfs
- Configure exports:
echo "/home/developer/projects/nfs 192.168.1.0/24(rw,sync,no_root_squash)" >> /etc/exports
sudo /etc/init.d/nfs-kernel-server restart
LED Driver Implementation
LED driver for STM32MP157 using GPIOI0:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/fs.h>
#define LED_DRIVER_MAJOR 201
#define LED_DEVICE_NAME "led_driver"
/* Register addresses */
#define GPIO_BASE (0x5000A000)
#define GPIO_MODER (GPIO_BASE + 0x00)
#define GPIO_OTYPER (GPIO_BASE + 0x04)
#define GPIO_OSPEEDR (GPIO_BASE + 0x08)
#define GPIO_PUPDR (GPIO_BASE + 0x0C)
#define GPIO_BSRR (GPIO_BASE + 0x18)
static void __iomem *gpio_moder;
static void __iomem *gpio_otyper;
static void __iomem *gpio_ospeedr;
static void __iomem *gpio_pupdr;
static void __iomem *gpio_bsrr;
static void led_control(int state) {
u32 value = readl(gpio_bsrr);
if (state == 1) {
value |= (1 << 0); // Set bit 0
} else {
value |= (1 << 16); // Set bit 16
}
writel(value, gpio_bsrr);
}
static int led_open(struct inode *inode, struct file *file) {
return 0;
}
static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) {
char state;
if (copy_from_user(&state, buf, 1) != 0)
return -EFAULT;
led_control(state);
return 1;
}
static int led_release(struct inode *inode, struct file *file) {
return 0;
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.release = led_release,
};
static int __init led_init(void) {
int ret;
u32 reg_val;
/* Map registers */
gpio_moder = ioremap(GPIO_MODER, 4);
gpio_otyper = ioremap(GPIO_OTYPER, 4);
gpio_ospeedr = ioremap(GPIO_OSPEEDR, 4);
gpio_pupdr = ioremap(GPIO_PUPDR, 4);
gpio_bsrr = ioremap(GPIO_BSRR, 4);
/* Enable GPIOI clock */
reg_val = readl(gpio_moder);
reg_val |= (1 << 8);
writel(reg_val, gpio_moder);
/* Configure GPIOI0 as output */
reg_val = readl(gpio_moder);
reg_val &= ~(0x3 << 0);
reg_val |= (0x1 << 0);
writel(reg_val, gpio_moder);
/* Set output type as push-pull */
reg_val = readl(gpio_otyper);
reg_val &= ~(1 << 0);
writel(reg_val, gpio_otyper);
/* Set speed to high */
reg_val = readl(gpio_ospeedr);
reg_val &= ~(0x3 << 0);
reg_val |= (0x2 << 0);
writel(reg_val, gpio_ospeedr);
/* Set pull-up */
reg_val = readl(gpio_pupdr);
reg_val &= ~(0x3 << 0);
reg_val |= (0x1 << 0);
writel(reg_val, gpio_pupdr);
/* Turn off LED initially */
led_control(0);
ret = register_chrdev(LED_DRIVER_MAJOR, LED_DEVICE_NAME, &led_fops);
if (ret < 0)
return ret;
return 0;
}
static void __exit led_exit(void) {
iounmap(gpio_moder);
iounmap(gpio_otyper);
iounmap(gpio_ospeedr);
iounmap(gpio_pupdr);
iounmap(gpio_bsrr);
unregister_chrdev(LED_DRIVER_MAJOR, LED_DEVICE_NAME);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Embedded Systems Team");
Driver Testing Application
Application to control the LED driver:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#define LED_ON 1
#define LED_OFF 0
int main(int argc, char *argv[]) {
int fd;
char buffer[2];
if (argc != 3) {
printf("Usage: %s <device> <state>\\n", argv[0]);
printf("State: 0 = off, 1 = on\\n");
return 1;
}
fd = open(argv[1], O_RDWR);
if (fd < 0) {
perror("open");
return 1;
}
buffer[0] = atoi(argv[2]);
write(fd, buffer, 1);
close(fd);
return 0;
}