Function Pointers inside Struct in C

#include <stdio.h>

typedef struct{
	int x;
	int y;
	int (*addXPoints) (int x,int y);
	int (*subXPoints) (int x,int y);
}Point;

int addPoints_x(int p1, int p2)
{
		return (p1+p2);
}	

int subtracteXPoints(int p1,int p2)
{
		return (p1-p2);
}

void printPointDetails(Point* temp)
{
		printf("Point [x,y] : %d , %d \n", temp->x, temp->y);
}

int main()
{
	Point p1={30,30};
	
	//another way to initialize
	//p1.x=10; 
	//p1.y=20;
	p1.addXPoints=addPoints_x;
	p1.subXPoints=subtracteXPoints;
	
	printPointDetails(&p1);
	
	printf("Total X Value of p1,p2 : %d\n",p1.addXPoints(p1.x,p1.x));
	printf("Total X Value of p1,p2 : %d\n",p1.subXPoints(p1.x,p1.x));
	

	return 0;
}

Constant pointers and Pointers to constant in C

#include <stdio.h>
int main()
{
	int val = 250;
	int val2 =300;

        // ptrInt is a pointer to integer constant
        const int* ptrInt = &val; //Pointer to Constant

        // ptrInt1 is a constant pointer to integer
        int* const ptrInt1 = &val; //Constant Pointer

        *ptrInt = 500; //pointer to constant wont allow

	ptrInt1 = &val2; //constant pointer wont allow

	return 0;
}

Another version of a simple char driver (Using x86_64 VMware)

Once the module is Live, Use
HEAD -c {no.of.bytes} /dev/mycharDevice for read operation
echo “” > /dev/mycharDevice for write operation

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#define DEVICE_NAME "mycharDevice"
#define CLASS_NAME "mycharClass"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("PraveenMax");

//Function prototypes for file_op
static int device_open(struct inode *, struct file *);
static int device_close(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t , loff_t *);
static ssize_t device_write(struct file *, const char *, size_t , loff_t *);

static struct file_operations my_fops={
	.owner = THIS_MODULE,
	.read  = device_read,
	.write = device_write,
	.open  = device_open,
	.release = device_close,
};	

//module variables
static struct class* mycharClass = NULL;
static struct device* mycharDevice = NULL;
static int majorNumber;

static char myBuffer[100]={0};
static short readPos=0;
static int times = 0;

static int device_open(struct inode *inode, struct file *filep)
{
	times++;
	printk(KERN_ALERT "MYCHARDEVICE Device opened %d times \n",times);
	return 0;
}

static int device_close(struct inode *inode, struct file *fileop)
{
	printk(KERN_ALERT "MYCHARDEVICE Device closed\n");
	return 0;
}

//Read len length of data from kernel buffer and stores in userbuffer "buff"
static ssize_t device_read(struct file *fileop, char *buff, size_t len, loff_t *f_pos)
{
	printk(KERN_ALERT "Reading from the device of Data length : %d \n", len);
	
	int bytesRead = 0;
	
	while(len>0)
	{
		//copies the kernel buffer "myBuffer" into userbuffer buff
		put_user(myBuffer[readPos++], buff++);
		len--;
		bytesRead++;
	}
	
	return bytesRead;
}

//Writes the data from userbuffer "buff" of length "len" into kernel buffer "msg"s
static ssize_t device_write(struct file *fileop, const char *buff, size_t len, loff_t *off)
{
	printk(KERN_ALERT "Writing to the device. Data length : %d \n", len);
	
	int bytesWritten = 0; //also acts as buffer index
	memset(myBuffer,0,100); //reset the buffer values
	readPos=0;//reset kernelbuffer pointer
	
	while(len >0)
	{
		myBuffer[bytesWritten] = buff[bytesWritten];
		bytesWritten++;
		len--;
	}

	return bytesWritten;
}
 
static int __init load_module(void)
{
	printk(KERN_ALERT "Mychardriver :: Loading the module \n");

	//Dynamically get the Major Number
	majorNumber = register_chrdev(0, DEVICE_NAME, &my_fops);

	if(majorNumber < 0)
	{
		printk(KERN_ALERT "*** Unable to register MYCHARDRIVER driver : %d\n", majorNumber);
		return majorNumber;
	}
	
	printk(KERN_ALERT "Obtained a Major number !\n");

	//Create a device class for my char driver (appears in /sys/class )
	mycharClass = class_create(THIS_MODULE, CLASS_NAME);
	if(IS_ERR(mycharClass))
	{
		unregister_chrdev(majorNumber, DEVICE_NAME);
		printk(KERN_ALERT "Failed to register the char device \n");
		return PTR_ERR(mycharClass);
	}
	printk(KERN_ALERT "Device class created successfully!\n");

	
	//Create the device node and register it (appears in /dev/DEVICE_NAME )
	mycharDevice = device_create(mycharClass, NULL, MKDEV(majorNumber,0), NULL, DEVICE_NAME);
	if(IS_ERR(mycharDevice))
	{
		class_destroy(mycharClass);
		unregister_chrdev(majorNumber, DEVICE_NAME);
		printk(KERN_ALERT "Failed the create Device node ! \n");
		return PTR_ERR(mycharDevice);
	}
	printk(KERN_ALERT "Device node created successfully ! \n");

	//some initializations
	memset(myBuffer,0,100); //reset the buffer values


 	return 0;
}

static void __exit unload_module(void)
{
	device_destroy(mycharClass, MKDEV(majorNumber, 0) );//destroy the device
	class_unregister(mycharClass);						 //Unregister the device class
	class_destroy(mycharClass); 						 //destroy the class
	unregister_chrdev(majorNumber, DEVICE_NAME);    	 //Unregister the major number
	printk(KERN_ALERT "MYCHARDRIVER Module exited!!\n");
} 

module_init(load_module);
module_exit(unload_module);

A minimal char device driver for arm linux

/*
 * SimpleCharDevice.c
 *
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>

#define DEVICE_NAME "SimpleCharDevice"
#define CLASS_NAME "SimpleCharDeviceClass"

MODULE_AUTHOR("PraveenMax");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A simple char device driver for BBB");
MODULE_VERSION("0.1");

static int majorNumber;//For device driver
static int devOpenCount=0;
static struct class* simpleCharClass = NULL;
static struct device* simpleCharDevice = NULL;
static short size_of_message;//used to store the length of previously written string
static char message[256]={0};

//File operations prototypes
static int dev_open(struct inode *, struct file *);
static int dev_release(struct inode *, struct file *);
static ssize_t dev_read(struct file *, char *, size_t, loff_t *);
static ssize_t dev_write(struct file *,const char *, size_t, loff_t *);

//our custom file-operation struct.
static struct file_operations fops={
		.open=dev_open,
		.release=dev_release,
		.read=dev_read,
		.write=dev_write,
		.owner= THIS_MODULE,
};

static int __init loadModule(void){

	printk(KERN_ALERT "Initializing the SimpleChar LKM\n");

	//try to dynamically allocate the Major number
	majorNumber = register_chrdev(0, DEVICE_NAME, &fops);
	if(majorNumber < 0)
	{
		printk(KERN_ALERT "Failed to register a major number\n");
		return majorNumber;
	}

	printk(KERN_ALERT "Registered Successfully with major number : %d\n",majorNumber);

	//Register the device class
	simpleCharClass = class_create(THIS_MODULE, CLASS_NAME);
	if(IS_ERR(simpleCharClass)){
		//if error found, unregister it
		unregister_chrdev(majorNumber, DEVICE_NAME);
		printk(KERN_ALERT "Failed to register the device class\n");
		return PTR_ERR(simpleCharClass);
	}

	printk(KERN_ALERT "Device class registered successfully\n");

	//Register the device driver
	simpleCharDevice = device_create(simpleCharClass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
	if( IS_ERR(simpleCharDevice)){
		class_destroy(simpleCharClass);
		unregister_chrdev(majorNumber, DEVICE_NAME);
		printk(KERN_ALERT "Failed to create the device\n");
		return PTR_ERR(simpleCharDevice);
	}

	printk(KERN_INFO "Device class created correctly\n");
	return 0;
}

static void __exit unloadModule(void){
	//device_destory(simpleCharClass, MKDEV(majorNumber,0));
	class_unregister(simpleCharClass);
	class_destroy(simpleCharClass);
	unregister_chrdev(majorNumber, DEVICE_NAME);
	printk(KERN_ALERT "Goodbye from SimpleCharDevice\n");
}

static int dev_open(struct inode *inodep, struct file *filep){
	devOpenCount++;
	printk(KERN_ALERT "SimpleCharDevice has been opened for %d times\n", devOpenCount);
	return 0;
}

static int dev_release(struct inode *inodep, struct file *filep){
	printk(KERN_ALERT "SimpleCharDevice successfully closed\n");
	return 0;
}

//Send char from KERNEL to USER
static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset){
	int error_count = 0;

	error_count = copy_to_user(buffer, message, size_of_message);

	if(error_count==0){
		printk(KERN_ALERT "SimpleCharDevice :: Sent %d characters to the user\n", size_of_message);
		printk(KERN_ALERT "OUTPUT : %s", message);
		size_of_message = 0;//reset the size_of_message
		return 0;
	}
	else{
		printk(KERN_ALERT "SimpleCharDevice :: Failed to send %d characters to the user\n", error_count);
		return -EFAULT;
	}
}

//Send char from USER to KERNEL
static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
	/*
	sprintf(message, "%s(%zu letters)", buffer, len);
	size_of_message = strlen(message);
	printk(KERN_ALERT "SimpleCharDevice :: Received %d chars from USER \n", len);
	return len;
	*/

	if(copy_from_user(message, buffer, len )!=0)
	{
		printk(KERN_ALERT "SimpleCharDevice :: Write failed!!\n");
	}
	else
	{
		printk(KERN_ALERT "SimpleCharDevice :: Write succeeded\n");
		size_of_message = strlen(message);
	}

	return len;

}

module_init(loadModule);
module_exit(unloadModule);

DC motor controlled using L239D motor driver IC with ATMEGA328


#include <avr/io.h>
#include <util/delay.h>

int main(void)
{

    //control pins
    DDRB|= 1<<PB0; //D1 on L293D 
    DDRB|= 1<<PB1; //D2 on L293D
  
    while(1)
    {

      //Rotate in clockwise direction
      PORTB&=~ (1<<PB0);
      PORTB|= 1<<PB1;
      _delay_ms(2000);

      
      //Rotate in anti-clockwise direction
      PORTB|=  1<<PB0;
      PORTB&=~ (1<<PB1);
      _delay_ms(2000);

    }
}


4×4 keypad interfacing using ATMEGA328p

#include <avr/io.h>
#include <util/delay.h>

#define KeypadDDR DDRD
#define KeypadPortControl PORTD
#define KeypadPinValue PIND

#define LedDDR DDRC
#define LedPortControl PORTC

void KeypadScan()
{
 
  _delay_ms(10);

  //Set Cols as INPUT and ROWS as OUTPUT
  KeypadDDR = 0b11100000;         _delay_ms(1);
  KeypadPortControl = 0b00011111; _delay_ms(1);

  //scan the keypad
  uint8_t keyPressCode = KeypadPinValue;

  if( keyPressCode == 0b00011011 ) //If C1 becomes LOW
  {
     //Set Cols as OUTPUT and ROWS as INPUT
     KeypadDDR = 0b00011100;          _delay_ms(1);
     KeypadPortControl = 0b11100011;  _delay_ms(1);

     //Read the input again
     keyPressCode = KeypadPinValue;
     
     if( keyPressCode == 0b11000011 ) LedPortControl = 0b00000001; //If R1 becomes LOW
     if( keyPressCode == 0b10100011 ) LedPortControl = 0b00000010; //If R2 becomes LOW
     if( keyPressCode == 0b01100011 ) LedPortControl = 0b00000100; //If R3 becomes LOW
   
  }

  if( keyPressCode == 0b00010111 ) //If C2 becomes LOW
  {
     //Set Cols as OUTPUT and ROWS as INPUT
     KeypadDDR = 0b00011100;          _delay_ms(1);
     KeypadPortControl = 0b11100011;  _delay_ms(1);

     //Read the input again
     keyPressCode = KeypadPinValue;
     
     if( keyPressCode == 0b11000011 ) LedPortControl = 0b00001000; //If R1 becomes LOW
     if( keyPressCode == 0b10100011 ) LedPortControl = 0b00010000; //If R2 becomes LOW
     if( keyPressCode == 0b01100011 ) LedPortControl = 0b00100000; //If R3 becomes LOW
   
  }
  
  _delay_ms(100);

  //turn off all lights
  LedPortControl = 0b00000000;
}

int main(void)
{
  //4x3 matrix keypad(Bit 1,2 are  unused)
   KeypadDDR         = 0b11100000;// Rows = 111 , Cols = 000
   KeypadPortControl = 0b00011111;// Rows = 000 , Cols = 111

   LedDDR         = 0b00111111;
   LedPortControl = 0b00000000; // quick led test OFF
   LedPortControl = 0b00111111; // 
   _delay_ms(100);
    while(1)
    {
      KeypadScan();
    }//while
  return 0;
}

Setting up Atmel Studio 7 for arduino boards

Steps as follows,

  1. Download Atmel Studio 7 .
  2. Go to Tools -> External Tools .
  3. Click Add and enter the following details,
    1. Title : Arduino_via_Bootloader (can be anything)
    2. Command : (path to your avrdude.exe)
      H:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe  
    3. Arguments : (path to your avrdude.conf + atmel dir specifics)
      -C”H:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf” -v -v -v -v -patmega328p -carduino -PCOM6 -b115200 -D -Uflash:w:”$(ProjectDir)Debug\$(TargetName).hex”:i

 

atmel_setup

16×2 LCD(1602A) interfacing with ATMEGA328p 4-bit mode

The code is not tested for output.
Blocks are shown instead of chars.

#include <avr/io.h>
#include <util/delay.h>

#define LCD_DATA_DDR DDRD
#define LCD_CTRL_DDR DDRB
#define LCD_DataBus PORTD  //Using PD4 to PD7
#define LCD_CTRL_PORT PORTB

//function prototypes
void LCD_Write(unsigned char cmd, unsigned char reg_select);
void LCD_WriteData(char data);
void LCD_WriteCmd(char cmd);
void LCD_Init();

void LCD_Write(unsigned char cmd, unsigned char reg_select)
{
  char  tempCmd;
  if(reg_select == 1)
    LCD_CTRL_PORT |= (1<<PB0);   //Select Data Register
  else
    LCD_CTRL_PORT &= ~(1<<PB0);   //Select Command Register

  //Mask data/cmd
  tempCmd = cmd;
  tempCmd &= 0xf0;// mask Lower 4 bits

  //Set data/cmd
  LCD_DataBus &= 0xf0;           //Set PORTD LSB to HIGH since we use PD4 to PD7
  LCD_DataBus |= tempCmd;        //Set bits in PORTD

  //Send data/cmd
  LCD_CTRL_PORT |= (1<<PB1); // Send a High-to-Low pulse at Enable pin
  _delay_ms(400);
  LCD_CTRL_PORT &= ~(1<<PB1); // Send a High-to-Low pulse at Enable pin

  //******Send next 4bits

  //mask data/cmd
  tempCmd = cmd << 4; //shift left 4 times so the LSB bit can be sent.
  tempCmd &= 0xf0; //mask Lower 4 bits

  //Set data/cmd in bus
  LCD_DataBus &= 0xf0;
  LCD_DataBus |= tempCmd;

  //Send data/cmd
  LCD_CTRL_PORT |= (1<<PB1); // Send a High-to-Low pulse at Enable pin
  _delay_ms(400);
  LCD_CTRL_PORT &= ~(1<<PB1); // Send a High-to-Low pulse at Enable pin

  return ;
}

//Send data by setting RS=1.
void LCD_WriteData(char data)
{
  LCD_Write(data, 1);
}

//Send cmd by setting RS=0.
void LCD_WriteCmd(char cmd)
{
  LCD_Write(cmd, 0);
}

void LCD_Init()
{
    LCD_WriteCmd(0x02); // to initialize LCD in 4-bit mode.
    _delay_ms(1);
    LCD_WriteCmd(0x28); //to initialize LCD in 2 lines, 5X7 dots and 4bit mode.
    _delay_ms(1);
    LCD_WriteCmd(0x01); // clear LCD
    _delay_ms(1);
    LCD_WriteCmd(0x0E); // cursor ON
    _delay_ms(1);
    LCD_WriteCmd(0x80); // —8 go to first line and –0 is for 0th position
    _delay_ms(1);
    return;
}

int main(void)
{
    LCD_DATA_DDR |= 0xf0;  //set the LCD DDRD to output
    LCD_CTRL_DDR |= 0b00000011; //For RS, E

    LCD_Init();
    _delay_ms(30);
    LCD_WriteData('a');
    LCD_WriteData('2');
    while(1)
    {

    }//while
}

LED blink looping in C

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  DDRD = 0b11111111; //led test
  PORTD = 0b00000000;
  unsigned char pinNo = 0;
  while(1)
  {
    while(pinNo<8)
    {
       PORTD = 0x00;
       PORTD |= 1<<pinNo;
       if(pinNo>=7)
          pinNo=0;
       else
          pinNo++;

      _delay_ms(500);

    }
  }
}

Reading input pin in avr using Embedded C

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  DDRD |=  0<<PD2;//PD2 is set to Input
  PORTD |= 1<<PD2;//pull-up activated.So, PD2 is high by default

  DDRB |= 1<<PB5 ;
  PORTB |= 0<<PB5 ;
  char portDVal = 0;
  while(1)
  {

      _delay_ms(100);
      portDVal = PIND;

      if( portDVal & (1<<PD2) )//if PD2 is HIGH(value read is 1)
      {
        PORTB &= ~(1<<PB5);
        _delay_ms(50);
      }
      else//if PD2 is LOW(value read is 0)
      {
        PORTB |= (1<<PB5);
        _delay_ms(50);
      }
  }
}