Raspbery pi fails writing to memory to initialize the function alt0 - linux-kernel

I am trying to write a raspy driver for pin 4.
while setting the alt0 function, raspy hangs, i have to restart it again.
#define RPI_DQ_GPIO_PIN 4
#define FUN_ALT0_SET 0x4
ds18b20_gpio_function(RPI_DQ_GPIO_PIN, FUN_ALT0_SET);
and
extern inline void ds18b20_gpio_function(u8 pin, u16 gpio_fun)
{
u32 val;
void __iomem *base_addr = (void __iomem *)(0xf2200000);
u8 offset = (pin / 10) * 4;
pin = (pin % 10) * 3;
val = gpio_fun << pin;
printk("ds18b20_gpio_function : pin = %d, val = %x, base_address + offset = %x\n", pin, val, base_addr + offset);
write_to_reg(val, base_addr + offset);
}
and
inline void write_to_reg(u32 b, volatile void __iomem *addr)
{
printk(KERN_INFO "write_to_reg : address = %x, b = %ld\n", addr, b);
__raw_writel(b, addr);
mb();
}
I got this virtual address of ioremap after dmesged of default gpio driver.
How can i solve it ?
Any help will be appreciated.
Thanks,

Related

problem in synchronization of timer0 and CPU clock cycles

I am a beginner in AVR. I need to sample input at odd intervals of 8 ms. i have used CTC mode for generating 8 ms timer. i used CTC with compare interrupt so that i can get a flag (timer_count) set at every comparison. i.e. after every 8 ms. The 8 ms timer starts on External Interrupt at PIN D0.
when i am checking the input conditions in main loop, due to large difference in frequency of main controller (18.432 MHz) and 8 ms timer, i am unable to sample inputs correctly. Can anyone tell me any other method to do this. The code is pasted here for reference.
#include <mega128.h>
#include <stdio.h>
#include <stdlib.h>
#define CHECK_BIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define SET_BIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEAR_BIT(ADDRESS,BIT) (ADDRESS &= (~(1<<BIT)))
#define TGL_BIT(ADDRESS, BIT) (ADDRESS ^= (1<<BIT))
volatile unsigned int flag;
volatile unsigned int timer_count=0;
volatile unsigned int frequency_979_sense;
volatile unsigned int frequency_885_sense;
volatile unsigned int frequency_933_sense;
volatile unsigned int flag_979_received;
volatile unsigned int flag_885_received;
volatile unsigned int data;
volatile unsigned int i;
volatile unsigned char SOP_valid;
volatile unsigned int previous_state=0;
volatile unsigned int current_state=0;
// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
timer_count++;
}
void init_timer0()
{
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 18.000 kHz
// Mode: CTC top=OCR0
// OC0 output: toggle output on compare match
ASSR=0x00;
TCCR0=0x1F;
TCNT0=0x00;
OCR0=0x90;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x02;
}
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if ((CHECK_BIT(PIND,4)==0) & (CHECK_BIT(PIND,5)==0))
{
init_timer0();
flag=1;
CLEAR_BIT(EIMSK,0);
CLEAR_BIT(EIFR,0);
}
}
void main(void)
{
// Port D initialization
PORTD=0xFF;
DDRD=0x00;
// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Rising Edge
EICRA=0x03;
EICRB=0x00;
EIMSK=0x01;
EIFR=0x01;
// Global enable interrupts
#asm("sei")
while (1)
{
while (timer_count > 0 & timer_count<32)
{
if (timer_count%2==1)
{
frequency_979_sense= CHECK_BIT(PIND,0);
frequency_885_sense= CHECK_BIT(PIND,4);
frequency_933_sense= CHECK_BIT(PIND,5);
if ((frequency_979_sense != 0) && (frequency_885_sense == 0) && (frequency_933_sense == 0) && (flag_885_received==0 || flag_885_received== 8))
{
flag_979_received++;
SET_BIT(data,i);
}
if ((frequency_979_sense == 0) && (frequency_885_sense != 0) && (frequency_933_sense == 0) && (flag_979_received==6))
{
flag_885_received++;
SET_BIT(data,i);
}
else
{
flag_979_received=0;
flag_885_received=0;
frequency_979_sense=0;
frequency_885_sense=0;
frequency_933_sense=0;
data=0;
TCCR0=0x00;
TIMSK=0x00;
timer_count=0;
i=0;
SET_BIT(EIMSK,0);
SET_BIT(EIFR,0);
}
}
i++;
}
if (data==65535)
{
SOP_valid=1;
}
}
}

Issue while reading data from I2c Slave device with PIC16F886

I am newbie to Pic Programming, I am using MPLAb & Hitech compiler to execute above code. I am trying to Interface PIC16F886 with ISL12022M Real time I2C device. i copied code example written for DS1307 interface with 16F887A PIC. I have capable to inteface Basic functionality with above . In below code While write into ISL12022M o could able to see data what i have send in memory register But as when Trying to read rtc time i could able to read last memory write value From SSPBUF. let me know any error in below code.
once I2c read value should be displayed on 4 digit seven segment display.
I think I am doing Misatake in this part. while Reading data i m just sending address so whatever last written in address it displaying.
#include <htc.h>
#include <stdio.h>
#include<pic.h>
#include<stdint.h>
#define _XTAL_FREQ 40000000
unsigned int i=0;
unsigned int k=0;
unsigned int count;
#define Pulse RA5
#define LED RC0
#define LED1 RC2
#define CONTROLREG 0xFF
#define SDA RC4 // Data pin for i2c
#define SCK RC3 // Clock pin for i2c
#define SDA_DIR TRISC4 // Data pin direction
#define SCK_DIR TRISC3 // Clock pin direction
#define DP RA4
#define I2C_SPEED 100 // kbps
unsigned short int cnt, num,Dgt=0;;
unsigned short int temp1,temp2,temp3;
unsigned short sec;
unsigned short min;
unsigned short hour;
unsigned short date;
unsigned short month;
unsigned short year;
unsigned short day;
unsigned short int temp=0;
unsigned short r_data;
#define Seg1 0x01
#define Seg2 0x02
#define Seg3 0x04
#define Seg4 0x08
void SetSeg(unsigned short data, unsigned short segno)
{
switch(data)
{
case 0: PORTB = 0x3F; break;
case 1: PORTB = 0x06; break;
case 2: PORTB = 0x5B; break;
case 3: PORTB = 0x4F; break;
case 4: PORTB = 0x66; break;
case 5: PORTB = 0x6D; break;
case 6: PORTB = 0x7D; break;
case 7: PORTB = 0x07; break;
case 8: PORTB = 0x7F; break;
case 9: PORTB = 0x6F; break;
default : PORTB = 0X00; break;
}
if(segno==1)
{
PORTA = Seg4;
}
if(segno==2)
{
PORTA = Seg3;
}
if(segno==3)
{
PORTA = Seg2;
}
if(segno==4)
{
PORTA = Seg1;
}
}
void Delay(int k)
{
int j;
for(j=0;j<k;j++);
}
void InitI2C(void)
{
SDA_DIR = 1; // Make SDA and
SCK_DIR =0; // SCK pins input
SSPCON = 0b00111000; //enables port for i2c
SSPCON2 = 0b00000000;
SSPADD = 10; // 100KHz = 8MHz/4(SSPADD+1)
// SSPSTAT = 0b11000000; // Slew rate disabled
}
void i2c_waitForIdle(void)
{
unsigned int i2ctimeout;
while(1)
{
i2ctimeout++;
if(i2ctimeout > 10)
{
i2ctimeout = 0;
return;
}
}
}
void I2C_Start(void)
{
SEN = 1; // Send start bit
i2c_waitForIdle();
/* while(!SSPIF); // Wait for it to complete
SSPIF = 0; // Clear the flag bit*/
}
void I2C_ReStart(void)
{
RSEN = 1; // Send Restart bit
i2c_waitForIdle();
/* while(!SSPIF); // Wait for it to complete
SSPIF = 0; // Clear the flag bit
while(RSEN==1);*/
}
void I2C_Stop(void)
{
PEN = 1; // Send stop bit
i2c_waitForIdle();
}
void I2C_Send_ACK(void)
{
ACKDT = 0; // 0 means ACK
ACKEN = 1; // Send ACKDT value
i2c_waitForIdle();
}
void I2C_Send_NACK(void)
{
ACKDT = 1; // 1 means NACK
ACKEN = 1; // Send ACKDT value
i2c_waitForIdle();
}
unsigned char I2C_Write( unsigned char i2cWriteData )
{
i2c_waitForIdle();
SSPBUF = i2cWriteData;
return (!ACKSTAT); // function returns '1'
}
int I2C_Read( unsigned char ack )
{
unsigned char i2cReadData;
//unsigned int i2cReadData;
i2c_waitForIdle();
RCEN = 1;
SDA=1;
SCK=1;
i2c_waitForIdle();
i2cReadData = SSPBUF;
SCK=0;
i2c_waitForIdle();
SCK=1;
if(ack)
{
ACKDT = 0;
}
else
{
ACKDT = 1;
}
ACKEN = 1; // send acknowledge sequence
return( i2cReadData );
}
unsigned int bcdtodecimal(unsigned int bcd)
{
unsigned int decimal;
decimal = (((bcd & 0xF0) >> 4) * 10) + (bcd & 0x0F);
return decimal;
}
void Init_ISL12022M(void)
{
I2C_Start(); // Start I2C communication
I2C_Write(0XD0); //Write Device Address
I2C_Write(0X08); //
I2C_Write(0X41); // Write 0x00 to Control register to disable SQW-Out
I2C_Stop(); // Stop I2C communication after initilizing
}
unsigned int Write_ISL12022M(unsigned short address, unsigned short w_data)
{
I2C_Start(); // Start I2C communication
I2C_Write(0XD0);
I2C_Write(address); //write address to write data
I2C_Write(w_data); //write data into hexadecimal
I2C_Stop();//stop I2C communication
return(w_data);
}
unsigned short Read_ISL12022M(unsigned short address)
{
I2C_Start();
I2C_Write(address); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
I2C_Write(address);
I2C_ReStart();
I2C_Write(0xD1); //0x68 followed by 1 --> 0xD1
r_data=I2C_Read(0);
I2C_Stop();
return(r_data);
}
void SetDateTime()
{
I2C_Start();
I2C_Write(0xD0);
I2C_Write(0x00);
sec= Write_ISL12022M(0X00, 12); //01 sec
min = Write_ISL12022M(0X01,52); //01 sec
hour = Write_ISL12022M(0X02,9); //01 sec
day= Write_ISL12022M(0X03,7); //01 sec
date = Write_ISL12022M(0X04, 29); //01 sec
month =Write_ISL12022M(0X05,07); //01 sec
year = Write_ISL12022M(0X06,17); //01 sec
I2C_Stop();
}
void RTC_GetDateTime()
{
I2C_Start(); // Start I2C communication
I2C_Send_ACK();
sec = I2C_Read(1); // read second and return Positive ACK
I2C_Send_ACK();
min = I2C_Read(1); // read minute and return Positive ACK
I2C_Send_ACK();
hour= I2C_Read(0); // read hour and return Negative/No ACK
I2C_Send_ACK();
day = I2C_Read(1); // read weekDay and return Positive ACK
I2C_Send_ACK();
date= I2C_Read(1); // read Date and return Positive ACK
I2C_Send_ACK();
month=I2C_Read(1); // read Month and return Positive ACK
I2C_Send_ACK();
year =I2C_Read(0); // read Year and return Negative/No ACK
I2C_Send_ACK();
I2C_Stop(); // Stop I2C communication after reading the Date
}
void interrupt isr(void)
{
if(TMR1IF==1)
{
TMR1H=0xF6; // Load the time value(0xBDC) for 100ms delay
TMR1L=0x18; //Timer1 Interrupt for 65000
TMR1IF=0; // Clear timer interrupt flag
Dgt++;
if(Dgt>=5)
{
Dgt=0;
LED=!LED;
}
}
}
void Timer1_Interrupt()
{
INTCON = 0b00000000;
PIE1=0b00000001;
PIR1=0x01;
TMR1H=0x0B;
TMR1L=0xDC;
T1CON=0x31;
}
void Init_Controller()
{
cnt=100;
TRISC=0b01000000; // Intialize INput & output pheripherals
TRISB=0b10000000;
PORTB = 0b00000000;
TRISA=0b0000000;
ADCON0 = 0b00000000;
ANSEL = 0b00000000;
Timer1_Interrupt();
}
void main(void)
{
Init_Controller();
/* GIE=1;
PEIE=1;
TMR1IE=1; */
InitI2C();
Init_ISL12022M();
SetDateTime();
while(1)
{
RTC_GetDateTime();
SetSeg(year/ 10,2);
SetSeg(year%10,1);
}
}
The lines like:
I2C_Write(0XD0); //Write Device Address
are not a valid device addresses. Use 0xDE (or 0xAE for User SRAM)
From the datasheet:
Following a start condition, the master must output a Slave Address Byte. The 7 MSBs are the device identifiers. These bits are “1101111” for the RTC registers and “1010111” for the User SRAM.

How to know the values of CR registers from linux user and kernel modes

I would like to know the CR0-CR4 register values on x86. Can I write inline assembly to read it out? Are there any other methods? (e.g., does OS keep any file structures to record these values)
The Linux kernel has some function to read and write Control Registers, they are the read_crX and write_crX functions for the standard CR and xgetbv,xsetbv for the extended CR.
User mode applications need a LKM to indirectly use these functions.
In theory you just need to create a LKM with one or more devices and handle IO requests by reading or writing from CR. In practice you usually have more than one CPU, so you need to handle MP.
I used the kernel module for CPUID as a template and create this LKM.
CODE IS WITHOUT ANY WARRANTY, TESTED ON DEBIAN 8 ON 64 bit VM ONLY
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/fs.h> /* Needed for KERN_INFO */
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/smp.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cpu.h>
#include <linux/notifier.h>
#include <linux/uaccess.h>
#include <linux/gfp.h>
#include <asm/processor.h>
#include <asm/msr.h>
#include <asm/xcr.h>
#define MAKE_MINOR(cpu, reg) (cpu<<8 | reg)
#define GET_MINOR_REG(minor) (minor & 0xff)
#define GET_MINOR_CPU(minor) (minor >> 8)
#define XCR_MINOR_BASE 0x80
static int major_n = 0;
static struct class *ctrlreg_class;
struct ctrlreg_info
{
unsigned int reg;
unsigned long value;
unsigned int error;
};
static void ctrlreg_smp_do_read(void* p)
{
struct ctrlreg_info* info = p;
info->error = 0;
printk(KERN_INFO "ctrlreg: do read of reg%u\n", info->reg);
switch (info->reg)
{
case 0: info->value = read_cr0(); break;
case 2: info->value = read_cr2(); break;
case 3: info->value = read_cr3(); break;
case 4: info->value = read_cr4(); break;
#ifdef CONFIG_X86_64
case 8: info->value = read_cr8(); break;
#endif
case XCR_MINOR_BASE: info->value = xgetbv(0); break;
default:
info->error = -EINVAL;
}
}
static void ctrlreg_smp_do_write(void* p)
{
struct ctrlreg_info* info = p;
info->error = 0;
switch (info->reg)
{
case 0: write_cr0(info->value); break;
case 2: write_cr2(info->value); break;
case 3: write_cr3(info->value); break;
case 4: write_cr4(info->value); break;
#ifdef CONFIG_X86_64
case 8: read_cr8(); break;
#endif
case XCR_MINOR_BASE: xgetbv(0); break;
default:
info->error = -EINVAL;
}
}
static ssize_t ctrlreg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
unsigned int minor = iminor(file_inode(file));
unsigned int cpu = GET_MINOR_CPU(minor);
unsigned int reg = GET_MINOR_REG(minor);
struct ctrlreg_info info = {.reg = reg};
int err;
printk(KERN_INFO "ctrlreg: read for cpu%u reg%u\n", cpu, reg);
printk(KERN_INFO "ctrlreg: read of %zu bytes\n", count);
if (count < sizeof(unsigned long))
return -EINVAL;
printk(KERN_INFO "ctrlreg: scheduling read\n");
err = smp_call_function_single(cpu, ctrlreg_smp_do_read, &info, 1);
if (IS_ERR_VALUE(err))
return err;
printk(KERN_INFO "ctrlreg: read success: %x\n", info.error);
if (IS_ERR_VALUE(info.error))
return err;
err = copy_to_user(buf, &info.value, sizeof(unsigned long));
printk(KERN_INFO "ctrlreg: read copy result: %x ( %lu )\n", err, sizeof(unsigned long));
if (IS_ERR_VALUE(err))
return err;
printk(KERN_INFO "ctrlreg: read done\n");
return sizeof(unsigned long);
}
static ssize_t ctrlreg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
unsigned int minor = iminor(file_inode(file));
unsigned int cpu = GET_MINOR_CPU(minor);
unsigned int reg = GET_MINOR_REG(minor);
struct ctrlreg_info info = {.reg = reg};
int err;
printk(KERN_INFO "ctrlreg: write for cpu%u reg%u\n", cpu, reg);
printk(KERN_INFO "ctrlreg: write of %zu bytes\n", count);
if (count < sizeof(unsigned long))
return -EINVAL;
printk(KERN_INFO "ctrlreg: scheduling write\n");
err = copy_from_user((void*)buf, &info.value, sizeof(unsigned long));
printk(KERN_INFO "ctrlreg: write copy data: %x ( %lu )\n", err, sizeof(unsigned long));
if (IS_ERR_VALUE(err))
return err;
err = smp_call_function_single(cpu, ctrlreg_smp_do_write, &info, 1);
if (IS_ERR_VALUE(err))
return err;
printk(KERN_INFO "ctrlreg: write success: %x\n", info.error);
if (IS_ERR_VALUE(info.error))
return err;
printk(KERN_INFO "ctrlreg: write done\n");
return sizeof(unsigned long);
}
static void ctrlreg_can_open(void *p)
{
unsigned int* reg = p;
unsigned int reg_num = *reg;
unsigned int ebx, edx, eax, ecx;
unsigned int support_xgetbv, support_ia32e;
*reg = 0; //Success
printk(KERN_INFO "ctrlreg: can open reg %u\n", reg_num);
if (reg_num <= 4 && reg_num != 1)
return;
#ifdef CONFIG_X86_64
if (reg_num == 8)
return;
#endif
cpuid_count(0x0d, 1, &eax, &ebx, &ecx, &edx);
support_xgetbv = cpuid_ecx(1) & 0x04000000;
support_ia32e = cpuid_edx(0x80000001) & 0x20000000;
printk(KERN_INFO "ctrlreg: xgetbv = %d\n", support_xgetbv);
printk(KERN_INFO "ctrlreg: ia32e = %d\n", support_ia32e);
if (support_xgetbv && support_ia32e)
return;
printk(KERN_INFO "ctrlreg: open denied");
*reg = -EIO;
}
static int ctrlreg_open(struct inode *inode, struct file *file)
{
unsigned int cpu;
unsigned int reg;
unsigned int minor;
int err;
minor = iminor(file_inode(file));
cpu = GET_MINOR_CPU(minor);
reg = GET_MINOR_REG(minor);
printk(KERN_INFO "ctrlreg: open device for cpu%u reg%u\n", cpu, reg);
if (cpu >= nr_cpu_ids || !cpu_online(cpu))
return -ENXIO; /* No such CPU */
err = smp_call_function_single(cpu, ctrlreg_can_open, &reg, 1);
if (IS_ERR_VALUE(err))
return err;
return reg;
}
static const struct file_operations ctrlreg_fops =
{
.owner = THIS_MODULE,
.read = ctrlreg_read,
.write = ctrlreg_write,
.open = ctrlreg_open
};
static int ctrlreg_device_create(int cpu)
{
struct device *dev = NULL;
int i;
printk(KERN_INFO "ctrlreg: device create for cpu %d\n", cpu);
//CR0, 2-4, 8
for (i = 0; i <= 8; i++)
{
if ((i>4 && i<8) || i == 1)
continue; //Skip non existent regs
printk(KERN_INFO "ctrlreg: device cpu%dcr%d\n", cpu, i);
dev = device_create(ctrlreg_class, NULL, MKDEV(major_n, MAKE_MINOR(cpu, i)), NULL, "cpu%dcr%d", cpu, i);
if (IS_ERR(dev))
return PTR_ERR(dev);
}
//XCR0
for (i = 0; i <= 0; i++)
{
printk(KERN_INFO "ctrlreg: device cpu%dxcr%d\n", cpu, i);
dev = device_create(ctrlreg_class, NULL, MKDEV(major_n, MAKE_MINOR(cpu, (XCR_MINOR_BASE+i))), NULL, "cpu%dxcr%d", cpu, i);
if (IS_ERR(dev))
return PTR_ERR(dev);
}
return 0;
}
static void ctrlreg_device_destroy(int cpu)
{
int i;
//CR0, 2-4, 8
for (i = 0; i <= 8; i++)
{
if ((i>4 && i<8) || i == 1)
continue; //Skip non existent regs
device_destroy(ctrlreg_class, MKDEV(major_n, MAKE_MINOR(cpu, i)));
}
//XCR0
for (i = 0; i <= 0; i++)
device_destroy(ctrlreg_class, MKDEV(major_n, MAKE_MINOR(cpu, (XCR_MINOR_BASE+i))));
}
static int ctrlreg_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
int err = 0;
switch (action)
{
case CPU_UP_PREPARE:
err = ctrlreg_device_create(cpu);
break;
case CPU_UP_CANCELED:
case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
ctrlreg_device_destroy(cpu);
break;
}
return notifier_from_errno(err);
}
static struct notifier_block __refdata ctrlreg_class_cpu_notifier =
{
.notifier_call = ctrlreg_class_cpu_callback,
};
static char* ctrlreg_devnode(struct device *dev, umode_t *mode)
{
unsigned int minor = MINOR(dev->devt), cpu = GET_MINOR_CPU(minor), reg = GET_MINOR_REG(minor);
if (reg < XCR_MINOR_BASE)
return kasprintf(GFP_KERNEL, "crs/cpu%u/cr%u", cpu, reg);
else
return kasprintf(GFP_KERNEL, "crs/cpu%u/xcr%u", cpu, reg-XCR_MINOR_BASE);
}
int __init ctrlreg_init(void)
{
int err = 0, i = 0;
printk(KERN_INFO "ctrlreg: init\n");
if ((major_n = __register_chrdev(0, 0, NR_CPUS, "crs", &ctrlreg_fops)) < 0)
return major_n;
printk(KERN_INFO "ctrlreg: major number is %u\n", major_n);
ctrlreg_class = class_create(THIS_MODULE, "ctrlreg\n");
if (IS_ERR(ctrlreg_class))
{
err = PTR_ERR(ctrlreg_class);
goto out_chrdev;
}
printk(KERN_INFO "ctrlreg: class created\n");
ctrlreg_class->devnode = ctrlreg_devnode;
cpu_notifier_register_begin();
for_each_online_cpu(i)
{
err = ctrlreg_device_create(i);
if (IS_ERR_VALUE(err))
goto out_class;
}
__register_hotcpu_notifier(&ctrlreg_class_cpu_notifier);
cpu_notifier_register_done();
printk(KERN_INFO "ctrlreg: init success\n");
err = 0;
goto out;
out_class:
i = 0;
for_each_online_cpu(i)
{
ctrlreg_device_destroy(i);
}
cpu_notifier_register_done();
class_destroy(ctrlreg_class);
out_chrdev:
__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "ctrlreg");
out:
return err;
}
static void __exit ctrlreg_exit(void)
{
int cpu = 0;
cpu_notifier_register_begin();
for_each_online_cpu(cpu)
ctrlreg_device_destroy(cpu);
class_destroy(ctrlreg_class);
__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "ctrlreg");
__unregister_hotcpu_notifier(&ctrlreg_class_cpu_notifier);
cpu_notifier_register_done();
}
module_init(ctrlreg_init);
module_exit(ctrlreg_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Kee Nemesis 241");
MODULE_DESCRIPTION("Read and write Control Registers");
This module create the following dev nodes:
/dev/crs/cpu0/cr0
/dev/crs/cpu0/cr2
/dev/crs/cpu0/cr3
/dev/crs/cpu0/cr4
/dev/crs/cpu0/cr8
/dev/crs/cpu0/xcr0
/dev/crs/cpu1/cr0
/dev/crs/cpu1/cr2
/dev/crs/cpu1/cr3
/dev/crs/cpu1/cr4
/dev/crs/cpu1/cr8
/dev/crs/cpu1/xcr0
...
You can read/write these dev nodes. The minimum read/write length is 4 bytes on 32 bit system and 8 bytes on 64 bit ones (Linux do some buffering anyway).
To compile this LKM, save the code above as ctrlreg.c and create this Makefile
obj-m += ctrlreg.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
then use make to get ctrlreg.ko.
To load the module use sudo insmod ctrlreg.ko, to remove it sudo rmmod ctrlreg.
I have also written a small user mode utility to read CR:
CODE IS WITHOUT ANY WARRANTY, TESTED ON DEBIAN 8 ON 64 bit VM ONLY
#include <stdio.h>
#include <stdlib.h>
#define MAX_PATH 256
int main(int argc, char* argv[])
{
unsigned long cpu, reg;
FILE* fin;
char device[MAX_PATH];
unsigned long data;
if (argc < 3 || argc > 4)
return fprintf(stderr, "Usage:\n\t\t cr cpu reg [value]\n"), 1;
if (sscanf(argv[1], "cpu%u", &cpu) != 1)
return fprintf(stderr, "Invalid value '%s' for cpu\n", argv[1]), 2;
if (sscanf(argv[2], "cr%u", &reg) != 1 && sscanf(argv[2], "xcr%u", &reg) != 1)
return fprintf(stderr, "Invalid value '%s' for reg\n", argv[2]), 3;
if (argc == 4 && sscanf(argv[3], "%lu", &data) != 1)
return fprintf(stderr, "Invalid numeric value '%s'\n", argv[3]), 6;
snprintf(device, MAX_PATH, "/dev/crs/cpu%u/%s", cpu, argv[2]);
fin = fopen(device, argc == 4 ? "wb" : "rb");
if (!fin)
return fprintf(stderr, "Cannot open device %s\n", device), 4;
if (argc == 4)
{
if (fwrite(&data, sizeof(data), 1, fin) != 1)
return fprintf(stderr, "Cannot write device %s (%d)\n", device, ferror(fin)), 5;
}
else
{
if (fread(&data, sizeof(data), 1, fin) != 1)
return fprintf(stderr, "Cannot read device %s (%d)\n", device, ferror(fin)), 7;
printf("%016x\n", data);
}
fclose(fin);
return 0;
}
Save the code as cr.c and compile it.
To read cr0 of the second CPU you can use:
cr cpu1 cr0
To write the value 0 (be careful) into it
cr cpu1 cr0 0

Logical error in comparing character recieved in USART

I Want to compare the character recieved via RX pin of ATMEGA 8. WHy doesn't the comparison work?
int main()
{
DDRB = 0XFF;
UCSRB = (1<<RXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
UBRRL = 0X33;
char r;
while (1)
{
while(!(UCSRA&(1<<RXC)));
r = UDR;
if(r=='r') PORTB = 0XFF;
}
return 0;
}
Sample code for easy setting baud_rate
#define F_CPU 8000000UL // Chip CPU frequency here, prevents default 1MHz
#define USART_BAUDRATE 19200UL // Baud_rate here, baudrates: 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
#include <avr/io.h>
int main(void) {
DDRB = 0XFF;
UBRRL = BAUD_PRESCALE; // baud to low byte of the UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // baud to high byte of the UBRR register
UCSRB = (1<<RXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
char r;
while(1) {
//TODO:: Please write your application code
while(!(UCSRA&(1<<RXC)));
r = UDR;
if(r=='r') PORTB = 0XFF;
}
return 0;
}

printf for p89v664 prints junk characters from actual micro controller

I am trying to print message on serial terminal from p89v664 using following code,
#include<P89V66x.H>
#include<stdio.h>
char putchar(char c) {
if (c == '\n') {
while (!TI);
TI = 0;
S0BUF = 0x0d;
}
TI = 0;
S0BUF = c;
while (!TI);
return c;
}
int printf(char*str) {
unsigned int cnt = 0;
while(*str != '\0')
{
putchar(*str);
cnt++;
str++;
}
}
void delay(unsigned int i) {
int d = 100;
for(;i!=0;i--) {
for(;d!=0;d--);
d = 100;
}
}
int main(void) {
/**Serial init*/
S0CON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */
TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */
TH1 = 0xF6; /* TH1: reload value for 9600 baud */
TR1 = 1; /* TR1: timer 1 run */
TI = 1;
while(1) {
printf("Hello\n");
delay(300);
printf("Hello World\n");
delay(10000);
}
}
above program works fine till the time printf function definition in this program is not commented.
If printf function in above program is commented to use printf from standard library then junk characters are printed on serial console. (i used putty).
I used Keil uVision V4.14.4.0 compiler.
Is there anything missing?
I dont understand what is wrong with this program.
After some experiments i found that problem was with keil uVision4 evaluation version.
I compiled this code using sdcc and ran it and it worked. May be keil evaluation version's limitation was creating problem. Thank very much you Mellowcandle for all replies.
Edit:
#include <P89V66x.H>
#include<stdio.h>
void putchar(char c) {
TI = 0;
S0BUF = c;
if (c == '\n') {
while (!TI);
TI = 0;
S0BUF = 0x0d;
}
while (!TI);
}
int main(void) {
/**Serial init*/
unsigned short int c = 65334;
S0CON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */
TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */
/**For 11.0592 crystal
value should TH = -3 or
TH1 = FD*/
TH1 = 0xF6; /* TH1: reload value for 9600 baud for
18 Mhz cyrstal */
TR1 = 1; /* TR1: timer 1 run */
while(1) {
printf("Hello %u\n", c);
delay(300);
printf("Hello World %u\n" ,c);
delay(10000);
}
}
command used to compile this code is,
sdcc {filename}

Resources