I am using a VersaLogic Osprey Board and I am running Lubuntu 16.04 Xenial with GCC compiler 6.2.0. Writing in C, I cannot compile C++.
I am trying to read from the I/O address of the Watchdog timer, with the intent of later enabling it. According to the data sheet the I/O address is 1CA8 (WDT_CTL is the identifier of this address)
The code I have thus far is as follows:
#define WDT_CTL 0x1CA8
int main(void)
{
char *p_CTL = (char*) WDT_CTL;
printf("Attempting to print contents %c\n"),*p_CTL);
}
The code compiles, but I get a segmentation fault (core dumped) when I get to the important line, there are no other errors or warnings. As far as I know a seg fault is a "you can't access that memory location" error, but I am trying to read from the address that I found in the data sheet.
I have done some research and according to the datasheet the address I have is an I/O address, which seems to be different from a normal address. When I look at the address of a custom variable (char a) that address is 12 digits long as opposed to the four I am given for the watchdog timer.
Am I missing something? Is it a limitation of Lubuntu that I can no longer write directly to an I/O address? Do I need to use some specific command to do so? Do I need to enable something or change a setting?
Note that this thread is different from one with a similar title because that was done in Windows 7, not Lubuntu and that fix will not work here.
This is how I usually access the watchdog hardware:
This has worked on several different computers.
#include "watchdog.h"
#include <fcntl.h> /* open() */
#include <stdio.h> /* printf() */
#include <unistd.h> /* write() */
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#define APP_VERSION "1.1.0"
/* Look for the device in two places */
#define WD_KICK_DEV_NAME_1 "/dev/cs5535/gpio/5"
#define WD_KICK_DEV_NAME_2 "/dev/gpio/5"
#define WD_ENABLE_DEV_NAME_1 "/dev/cs5535/gpio/27"
#define WD_ENABLE_DEV_NAME_2 "/dev/gpio/27"
#define TEXT_WDOG_KICK "Ot0101"
#define TEXT_WDOG_ENABLE "1TO"
#define TEXT_WDOG_DISABLE "0TO"
static INT32 wd_kick_fd;
static INT32 wd_enable_fd;
/**
* Return the version
*/
const char *wd_get_version(void)
{
return(APP_VERSION);
}
/**
* Open GPIO-5 and GPIO-27
*/
INT32 wd_init(void)
{
if (((wd_kick_fd = open(WD_KICK_DEV_NAME_2, O_WRONLY)) < 0) &&
((wd_kick_fd = open(WD_KICK_DEV_NAME_1, O_WRONLY)) < 0))
{
printf("Failed to open '%s' or '%s': %s (%d)\n",
WD_KICK_DEV_NAME_1, WD_KICK_DEV_NAME_2, strerror(errno), errno);
return(FAILURE);
}
if (((wd_enable_fd = open(WD_ENABLE_DEV_NAME_2, O_WRONLY)) < 0) &&
((wd_enable_fd = open(WD_ENABLE_DEV_NAME_1, O_WRONLY)) < 0))
{
printf("Failed to open '%s' or '%s': %s (%d)\n",
WD_ENABLE_DEV_NAME_1, WD_ENABLE_DEV_NAME_2, strerror(errno), errno);
return(FAILURE);
}
return(SUCCESS);
}
/**
* Disabled via GPIO-27
*/
void wd_disable(void)
{
(void)write(wd_enable_fd, TEXT_WDOG_DISABLE, strlen(TEXT_WDOG_DISABLE));
}
/**
* Enabled via GPIO-27
*/
void wd_enable(void)
{
(void)write(wd_enable_fd, TEXT_WDOG_ENABLE, strlen(TEXT_WDOG_ENABLE));
}
/**
* Kick the watchdog by toggling GPIO 5
*/
void wd_kick(void)
{
(void)write(wd_kick_fd, TEXT_WDOG_KICK, strlen(TEXT_WDOG_KICK));
}
and the watchdog.h file contains:
#ifndef WATCHDOG_H_INCLUDED
#define WATCHDOG_H_INCLUDED
/**
* Grab the version of the kicker stuff
*/
const char *wd_get_version(void);
/**
* Do any initialization needed for the watchdog.
*
* #return SUCCESS or FAILURE
*/
INT32 wd_init(void);
/**
* Disables the watchdog.
* If watchdog cannot be disabled, then calls wd_kick()
*/
void wd_disable(void);
/**
* Enables the watchdog.
* If watchdog cannot be disabled, do nothing.
*/
void wd_enable(void);
/**
* Kicks the watchdog
*/
void wd_kick(void);
#endif /* WATCHDOG_H_INCLUDED */
Related
My goal is to write a kernel-module. I am following the memory tutorial of the freesoftware magazine.
The tutorial works fine. I am able to compile the code. When loaded with insmod, the kernel prints <1>Inserting memory module as expected. When I remove the module using rmmod the kernel prints <1>Removing memory module.
For debugging purposes, I am trying to add printk() to the other methods. But they are never printed.
The priority of all the messages is <1>.
I write into the device by: echo -n test1234 > /dev/memory
And use cat /dev/memory to get back the data.
cat /var/log/messages and dmesg donĀ“t print anymore information
[ 5550.651221] <1>Inserting memory module
[ 5550.655396] <1>Inserting memory module !!!!!!!!!!!!!!!
[12230.130847] <1>Removing memory module
cat /proc/sys/kernel/printk
7 4 1 7
uname- a
Linux generic-armv7a-hf 3.14.0-163850-g775a3df-dirty #2 SMP Mon Jan 12 13:53:50 CET 2015 armv7l GNU/Linux
Why does printk() only work in the init and exit method?
Is there any (better) way to print variable values than printk()?
Here the code:
/* Necessary includes for device drivers */
#include <linux/init.h>
//#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_from/to_user */
MODULE_LICENSE("Dual BSD/GPL");
/* Declaration of memory.c functions */
int memory_open(struct inode *inode, struct file *filp);
int memory_release(struct inode *inode, struct file *filp);
ssize_t memory_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
ssize_t memory_write(struct file *filp, char *buf, size_t count, loff_t *f_pos);
void memory_exit(void);
int memory_init(void);
/* Structure that declares the usual file */
/* access functions */
struct file_operations memory_fops = {
read: memory_read,
write: memory_write,
open: memory_open,
release: memory_release
};
/* Declaration of the init and exit functions */
module_init(memory_init);
module_exit(memory_exit);
/* Global variables of the driver */
/* Major number */
int memory_major = 60;
/* Buffer to store data */
char *memory_buffer;
int memory_init(void) {
int result;
/* Registering device */
result = register_chrdev(memory_major, "memory", &memory_fops);
if (result < 0) {
printk(
"<1>memory: cannot obtain major number %d\n", memory_major);
return result;
}
/* Allocating memory for the buffer */
memory_buffer = kmalloc(1, GFP_KERNEL);
if (!memory_buffer) {
result = -ENOMEM;
goto fail;
}
memset(memory_buffer, 0, 1);
printk("<1>Inserting memory module\n"); ///this works fine
printk("<1>Inserting memory module !!!!!!!!!!!!!!!\n"); ///this works fine too
return 0;
fail:
memory_exit();
return result;
}
void memory_exit(void) {
/* Freeing the major number */
unregister_chrdev(memory_major, "memory");
/* Freeing buffer memory */
if (memory_buffer) {
kfree(memory_buffer);
}
printk("<1>Removing memory module\n"); //never printed
}
int memory_open(struct inode *inode, struct file *filp) {
printk("<1>memory open\n"); //never printed
/* Success */
return 0;
}
int memory_release(struct inode *inode, struct file *filp) {
printk("<1>memory_release\n"); //never printed
/* Success */
return 0;
}
ssize_t memory_read(struct file *filp, char *buf,
size_t count, loff_t *f_pos) {
printk("<1>mem read\n"); //never printed
/* Transfering data to user space */
copy_to_user(buf,memory_buffer,1);
/* Changing reading position as best suits */
if (*f_pos == 0) {
*f_pos+=1;
return 1;
} else {
return 0;
}
}
ssize_t memory_write( struct file *filp, char *buf,
size_t count, loff_t *f_pos) {
printk("<1>mem write\n"); //never printed
char *tmp;
tmp=buf+count-1;
copy_from_user(memory_buffer,tmp,1);
return 1;
}
Your driver seems fine, but you aren't actually talking to it with your test commands, so the functions with printks aren't being called. Once the module is loaded, it registers a major and minor number, 60 and 0 in your case. (Down the road you should update the module to request an available major number instead of using a hard-coded one.)
You need to create a file system node with mknod in order to actually use the driver. This will create the /dev/memory node and connect it to the module you have loaded. Then when it is opened, closed, read from, or written to, the file_operations in your module will be called, and the printks will work.
For your module, you should be able to use
mknod /dev/memory c 60 0
You can also chmod 666 /dev/memory to allow any user to use the device, rather than running as root all the time.
Here's a script based on the one I use with modules I develop:
#!/bin/sh
device="memory"
mode="666"
major=$(awk "\$2==\"$device\" {print \$1}" /proc/devices}
mknod /dev/${device} c $major 0
chmod $mode /dev/${device}
It will look up the major number associated with your module and create a file system node for it automatically.
Once you have loaded the module and run mknod or the script, you should be able to use the driver. You will know that it is working becase cat will only return the last character written to the device - your driver only has a one character buffer, and it is automatically overwritten each time a new character comes in. Then dmesg should show the printk's associated with the functions in your module.
The reason your driver seemed to work is because you were creating a regular file with your echo command, which cat happily printed right back to you. It's the same thing that would have happened if you ran those commands on a file in your home directory, you just happened to be in /dev instead.
I am new to kernel and KLD programming. I am looking to modify the example file in FreeBSD for system call module. My question is, is it possible to fork or exec inside system call function? Like in the following example?
#include <sys/types.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>
/*
* The function for implementing the syscall.
*/
static int hello (struct thread *td, void *arg)
{
printf("Running...\n");
/******************************************************/
/*Something like this?*/
/******************************************************/
execl("/bin/pwd", "pwd", NULL);
return 0;
}
/*
* The `sysent' for the new syscall
*/
static struct sysent hello_sysent = {
0, /* sy_narg */
hello /* sy_call */
};
/*
* The offset in sysent where the syscall is allocated.
*/
static int offset = NO_SYSCALL;
/*
* The function called at load/unload.
*/
static int
load (struct module *module, int cmd, void *arg)
{
int error = 0;
switch (cmd) {
case MOD_LOAD :
uprintf ("syscall loaded at %d\n", offset);
break;
case MOD_UNLOAD :
uprintf ("syscall unloaded from %d\n", offset);
break;
default :
uprintf("There was some error!");
error = EINVAL;
break;
}
return error;
}
SYSCALL_MODULE(syscall, &offset, &hello_sysent, load, NULL);
There is no compilation error (syscall), but while loading it using kldload, it returns an error:
kldload: can't load ./syscall.ko: No such file or directory
Is there something I can read and know more about why is this happening and what can I do about it?
When kldload returns "No such file or directory", or some other weird error, first do "dmesg" and look for any errors at the bottom. In this case it's probably due to a missing symbol "execl". That's because execl is a userspace API (man 3 execl), and you're trying to use it in kernel.
What you're trying to do doesn't seem to be a good idea, but it's possible. Look at sys/kern/kern_exec.c:kern_execve().
Can someone please show me some example on how to read values from Raspberry Pi registers?
I need to check byte in AUX_MU_LSR_REG (0x7E21 5054) but i don't know how to do this without usage of any additional libraries.
I tried to:
(here i modify the oryginal post)
**************************Start of the code
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#define BCM2708 0x20000000
#define UART_BASE (BCM2708+0x215000)
#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)
int mem_fd;
void *uart_map;
volatile unsigned *uart;
int main()
{
printf("start\n");
if((mem_fd=open("/dev/mem",O_RDWR|O_SYNC))<0)
{
printf("can't open /dev/mem \n");
exit(-1);
}
else printf("stream_file open OK \n");
if((uart_map=malloc(BLOCK_SIZE))==0)
printf("malloc fail\n");
else printf("GPIO_mallocation OK %d \n", (int)uart_map );
uart_map=mmap (NULL, //any address in our space
BLOCK_SIZE, //map length
PROT_READ|PROT_WRITE, //Enable reading and writing to maped memmory
MAP_SHARED, //Shares with other processes
mem_fd, //File to map
UART_BASE //Offset toUART peripheral
);
if(uart_map==MAP_FAILED)
{
printf("mmap error %d", (int)uart_map);
exit(-1);
}
else printf("GPIO mapping OK \n");
uart=(volatile unsigned* )uart_map;
int i;
for(i=0;i<32;i++)
{
printf("adress:%x ",uart+i);
printf("value:%x\n",*(uart+i));
}
printf("stop\n");
return 0;
}
`
***********************end of code
Now i don't really remember how i display the 0 but in the above code i get pointer conflict.
What is the uart pointing to? In theory it should display the values but after few weeks i can't make it running.
Hope you can help me somehow
I've successfully compiled the example here and been able to read and write digital values from GPIO pins with a little modification to that code.
You're essentially heading in the right direction: mmap() a range specified in the datasheet for your particular GPIO, SPI or whichever register you need, and then read and write from that address. That's the basis of all the GPIO programming on the RPi.
There are some special bitfields that you should pay attention to, but as I mentioned, these are all in the datasheets for the Pi at elinux.org
note: to mmap() the system registers you need to be running as the superuser.
I am getting a segmentation fault when trying to read a port with inb_p( ). I'm compiling this on a Debian system running 2.6.6 kernel on an Intel D525 dual-core system (Advantech PCM 9389 SBC). Here is a sample program which illustrates the segfault.
What is the probable cause? How do I fix this?
Currently, I don't have any devices hooked up. Could this cause the segfault? I would have expected to get either a zero or some random byte, but not a segfault.
Other things I tried:
1) Declared the input variable as int instead of char.
2) Used iopl() instead of ioperm()
/*
* ioexample.c: very simple ioexample of port I/O
* very simple port i/o
* Compile with `gcc -O2 -o ioexample ioexample.c',
* and run as root with `./ioexample'.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/io.h>
#define BASEPORT 0x0100 /* iobase for sample system */
#define FLIPC 0x01
#define FLIPST 0x0
#define DIPSWITCH 0x25
int main()
{
char cinput;
cinput = 0xff;
setuid(0);
printf("begin\n");
/* Get access to the ports */
if (ioperm(BASEPORT+DIPSWITCH, 10, 1))
{
perror("ioperm");
exit(EXIT_FAILURE);
}
printf("read the dipswitch with pause\n");
cinput = inb_p(BASEPORT+DIPSWITCH); // <=====SEGFAULT HERE
/* We don't need the ports anymore */
if (ioperm(BASEPORT+DIPSWITCH, 10, 0))
{
perror("ioperm");
exit(EXIT_FAILURE);
}
printf("Dipswitch setting: 0x%X", cinput);
exit(EXIT_SUCCESS);
}
/* end of ioexample.c */
Output:
root#debian:/home/howard/sources# ./ioexample
begin
read the dipswitch with pause
Segmentation fault
Edit: /proc/ioports did not list anything at address 0x100, so I tried several other port addresses that were listed, with the same result. Then I decided to try an output to a known parallel port location (0x0378), and outb did not cause a segfault. However, trying to read either 0x378 or 0x379 did cause a segfault. I am beginning to suspect that the problem is hardware related.
I found the problem. The call to inb_p() requires access to port 0x80 in addition to the port to be read.
Apparently, when I tried iopl(), I didn't call it correctly, because that should have worked.
The following code eliminated the segfault:
/* Get access to the ports */
if (ioperm(0x80, 1, 1))
{
perror("ioperm");
exit(EXIT_FAILURE);
}
if (ioperm(BASEPORT+DIPSWITCH, 10, 1))
{
perror("ioperm");
exit(EXIT_FAILURE);
}
In C on FreeBSD, how does one access the CPU utilization?
I am writing some code to handle HTTP redirects. If the CPU load goes above a threshold on a FReeBSD system, I want to redirect client requests. Looking over the man pages, kvm_getpcpu() seems to be the right answer, but the man pages (that I read) don't document the usage.
Any tips or pointers would be welcome - thanks!
After reading the answers here, I was able to come up with the below. Due to the poor documentation, I'm not 100% sure it is correct, but top seems to agree. Thanks to everyone who answered.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <unistd.h>
#define CP_USER 0
#define CP_NICE 1
#define CP_SYS 2
#define CP_INTR 3
#define CP_IDLE 4
#define CPUSTATES 5
int main()
{
long cur[CPUSTATES], last[CPUSTATES];
size_t cur_sz = sizeof cur;
int state, i;
long sum;
double util;
memset(last, 0, sizeof last);
for (i=0; i<6; i++)
{
if (sysctlbyname("kern.cp_time", &cur, &cur_sz, NULL, 0) < 0)
{
printf ("Error reading kern.cp_times sysctl\n");
return -1;
}
sum = 0;
for (state = 0; state<CPUSTATES; state++)
{
long tmp = cur[state];
cur[state] -= last[state];
last[state] = tmp;
sum += cur[state];
}
util = 100.0L - (100.0L * cur[CP_IDLE] / (sum ? (double) sum : 1.0L));
printf("cpu utilization: %7.3f\n", util);
sleep(1);
}
return 0;
}
From the MAN pages
NAME
kvm_getmaxcpu, kvm_getpcpu -- access per-CPU data
LIBRARY
Kernel Data Access Library (libkvm, -lkvm)
SYNOPSIS
#include <sys/param.h>
#include <sys/pcpu.h>
#include <sys/sysctl.h>
#include <kvm.h>
int
kvm_getmaxcpu(kvm_t *kd);
void *
kvm_getpcpu(kvm_t *kd, int cpu);
DESCRIPTION
The kvm_getmaxcpu() and kvm_getpcpu() functions are used to access the
per-CPU data of active processors in the kernel indicated by kd. The
kvm_getmaxcpu() function returns the maximum number of CPUs supported by
the kernel. The kvm_getpcpu() function returns a buffer holding the per-
CPU data for a single CPU. This buffer is described by the struct pcpu
type. The caller is responsible for releasing the buffer via a call to
free(3) when it is no longer needed. If cpu is not active, then NULL is
returned instead.
CACHING
These functions cache the nlist values for various kernel variables which
are reused in successive calls. You may call either function with kd set
to NULL to clear this cache.
RETURN VALUES
On success, the kvm_getmaxcpu() function returns the maximum number of
CPUs supported by the kernel. If an error occurs, it returns -1 instead.
On success, the kvm_getpcpu() function returns a pointer to an allocated
buffer or NULL. If an error occurs, it returns -1 instead.
If either function encounters an error, then an error message may be
retrieved via kvm_geterr(3.)
EDIT
Here's the kvm_t struct:
struct __kvm {
/*
* a string to be prepended to error messages
* provided for compatibility with sun's interface
* if this value is null, errors are saved in errbuf[]
*/
const char *program;
char *errp; /* XXX this can probably go away */
char errbuf[_POSIX2_LINE_MAX];
#define ISALIVE(kd) ((kd)->vmfd >= 0)
int pmfd; /* physical memory file (or crashdump) */
int vmfd; /* virtual memory file (-1 if crashdump) */
int unused; /* was: swap file (e.g., /dev/drum) */
int nlfd; /* namelist file (e.g., /kernel) */
struct kinfo_proc *procbase;
char *argspc; /* (dynamic) storage for argv strings */
int arglen; /* length of the above */
char **argv; /* (dynamic) storage for argv pointers */
int argc; /* length of above (not actual # present) */
char *argbuf; /* (dynamic) temporary storage */
/*
* Kernel virtual address translation state. This only gets filled
* in for dead kernels; otherwise, the running kernel (i.e. kmem)
* will do the translations for us. It could be big, so we
* only allocate it if necessary.
*/
struct vmstate *vmst;
};
I believe you want to look into 'man sysctl'.
I don't know the exact library, command, or system call; however, if you really get stuck, download the source code to top. It displays per-cpu stats when you use the "-P" flag, and it has to get that information from somewhere.