I have some driver code that I am testing out for use with an SSD1306 driven OLED screen which is 128x32 (same as the OLED adafruit model). I need this to run in debian (I am using Linario-4.4.9)
I have followed the Debian guides on how to start creating a file handler for the device, this can be seen as follows below. The only thing in oled.h is the device adress (0x3C) and the proto types. I followed the initialization approach taken on the adafruit github (as I tried their code out first on an Ardunio to ensure the screen does in fact work). I believe I may be doing something wrong but I'm not entirely sure what I am doing wrong. I have also listed my init process below.
#include <errno.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <linux/i2c-dev.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include "oled.h"
int oled;
int lcd_driver_init(void)
{
///< Begin the init proc.
int dloc = open("/dev/i2c-1", O_RDWR);
if (dloc < 0 )
{
fprintf(stderr, "Error opening i2c device\n");
return -1;
}
if(ioctl(dloc, I2C_SLAVE, SCR_ADDR) < 0)
{
fprintf(stderr, "Error in ioctl. Errno :%i\n",errno);
return -2;
}
oled = dloc;
fprintf(stderr, "init success, device open and local\n");
return EXIT_SUCCESS;
}
int oled_command( uint8_t cmd)
{
char command[2]= {0};
command[1] = cmd;
int check = (write(oled, command, 2));
return check;
}
void oled_cmd_start()
{
int check = (write(oled, 0x00, sizeof(uint8_t)));
if(check<0)
fprintf(stderr, "Errno set:: %i\n", errno);
return;
}
void oled_data_start()
{
uint8_t _data_start_[1] ={ 0x40 };
int check = (write(oled, _data_start_, sizeof(uint8_t)));
if(check<0)
fprintf(stderr, "Errno set oled_data_start:: %i\n", errno);
return;
}
int oled_data (uint8_t xmit)
{
int check = (write(oled, &xmit, (sizeof(uint8_t))));
if(check<0)
fprintf(stderr, "Errno set oled_data:: %i\n", errno);
return check;
}
INIT PROCESS
void sendcommand(unsigned char payload)
{
oled_data(0x00); //Control Byte - Command
oled_data(payload); //payload
}
void lcd_init(void)
{
sendcommand(0xAE);//--Set Display off
sendcommand(0x00);//--set low column address
sendcommand(0x10);//--set high column address
sendcommand(0x81);//--set contrast control register
sendcommand(0x7f);
sendcommand(0xa1);//--set segment re-map 95 to 0
sendcommand(0xA6);//--set normal display
sendcommand(0xa8);//--set multiplex ratio(1 to 16)
sendcommand(0x1f);//--duty 1/32
sendcommand(0xd3);//--set display offset
sendcommand(0x00);//--not offset
sendcommand(0xd5);//--set display clock divide ratio/oscillator frequency
sendcommand(0xf0);//--set divide ratio
sendcommand(0xd9);//--set pre-charge period
sendcommand(0x22);
sendcommand(0xda);//--set com pins hardware configuration
sendcommand(0x02);//disable left/right remap and set for sequential
sendcommand(0xdb);//--set vcomh
sendcommand(0x49);//--0.83*vref
sendcommand(0x8d);//--set DC-DC enable
sendcommand(0x14);//
sendcommand(0xAF);//--turn on oled panel
sendcommand(0xA4);//--Entire Display ON
}
Following this, I send alternating 0xFF to try and make stripes on the screen. The only thing that shows up is random pixels. Nothing coherent.
I have connected a logic analyzer to sniff the I2C lines, and it appears that when I have the LA connected, the I2C lines no longer function and ERRNO returns an IO fault (#5).
There doesn't ever seem to be an issue opening up the device to get the file pointer however.
I do get ERRNO as timeout sometimes, but I have read that this is just an issue with I2C devices using the protocal as write expects a quicker response than I2C might give.
I am also compiling with -std=c99 -O0 to ensure all of the inline functions are there as well as ensuring that loop variables are available.
If anyone can point me in the right direction of can point out some flaw in my approach it would be much appreciated. Thank you.
EDIT
I've checked the device tree and the i2c device is correctly enabled. However none of the i2c_freq speeds seem to be enabled. Could this be causing the timeouts and the garbage data transfer?
I have connected a logic analyzer to sniff the I2C lines, and it appears that when I have the LA connected, the I2C lines no longer function and ERRNO returns an IO fault (#5).
logic analyzer is just a device for measurement. It converts the captured data into timing diagrams, decodes protocol which you have set. So it will not be responsible for any I2C read write error (until your grounding and h/w connections are correct).
For timeout issue either you can try by decreasing the i2c clock-frequency or ioctl I2C_TIMEOUT.
It turns out the SOM has an internal regulator for the I2C lines to be 1V8 where as the SSD1306 chip is running at 3V3 causing information to be mishandled. This behavior wasn't documented on the SOM.
Applying a level shifting chip to the design allowed for proper communication.
If someone has this same problem, check your schematics for voltage mismatch levels.
Related
I'm currently developing a contiki programm that runs on a Z1 device for debugging purposes. I would like to send UART messages to that device and found out that Cooja appears to supports that with a function called "Show serial port on Z1". That tool in fact helped me to read UART messages sent from the mote, but when I try to send somethin back, the Int handler just doesn't get called.
Here's how I initialize UART in code:
uart0_init(0);
uart0_set_input(uart_handler);
uart0_writeb('U');
In the handler itself, I just toggle all LEDs (which definitely works) - however, they never get toggled. I even tried to send a byte in the ISR handler within the uart0-library but even that byte never gets sent. This means that the whole UART communication between Cooja and the Z1 mote does not seem to work correctly. Has anyone ever had the same problem and is able to provide me with a solution for that? It would be a great help!
I did manage to figure it out in the mean time. Here's the solution for anybody who is facing the same problem.
The following code works. Depending on whether you define USE_SERIAL_LINE you can decide if you would like to use the serial-line-module or your own int handler.
#include <stdio.h>
#include <string.h>
#include "contiki.h"
#include "contiki-net.h"
#include "dev/uart0.h"
#define USE_SERIAL_LINE
#ifdef USE_SERIAL_LINE
#include "dev/serial-line.h"
#endif
PROCESS(init_system_proc, "Init system process");
AUTOSTART_PROCESSES(&init_system_proc);
int uart_handler(unsigned char c){
printf("Single Byte input.\n");
return 1;
}
PROCESS_THREAD(init_system_proc, ev, data){
PROCESS_BEGIN();
uart0_init(0);
#ifdef USE_SERIAL_LINE
serial_line_init();
uart0_set_input(serial_line_input_byte);
#else
uart0_set_input(uart_handler);
#endif
while (1) {
PROCESS_YIELD();
#ifdef USE_SERIAL_LINE
if(ev == serial_line_event_message)
printf("Serial input.\n");
#endif
}
PROCESS_END();
}
There's one thing you need to keep in mind when using printf for UART output. A UART message will only be send when "\n" appears - this means that every printf-statement should end with a new line character. Otherwise your string only gets buffered and send out once a new line character appears.
I am trying to do SPI transfer in a raspberry pi. Raspberry pi comes with an SPI interface which send and recieves the data through it GPIO(General purpose input output pins). The spi driver information is here. I am doing loopback (connect MOSI and MISO pins). I had describe in my code what data I am sending, This data I will recieve due to loopback. I want a calculation on the recieved data. These data are stored in the form of array. After the calculation I need to print the results with proper sign, but I am not getting it.Here is my complete code.
/************************All header should come here************************************************************************ ********************************/
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
/***************************All declaration should come here***************************************************************************************************/
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
static const char *device = "/dev/spidev0.0";//selecting spi device in the raspberry pi
static uint8_t mode;//mode of spi transfer
static uint8_t bits =8;//no. of bits to be transfer, Pi supports 8 bit transfer
static uint32_t speed = 32000000;//spi clock speed,32 MHz is the maximum supported clock frequency
static uint16_t delay;
/*****************************Function definition should come here**********************************************************************************************/
/*function for transfer*/
static void transfer(int fd)//declaring a function for the transfer, this should be call in main program for transfer
{
int ret;// a return variable
uint8_t tx[]={4,5,6,5,4,3,5,4};// Array initialization
uint8_t rx[ARRAY_SIZE(tx)]={0,};//recieving array should be same as transferred array
struct spi_ioc_transfer tr= { // standard structure for spi driver usage
.tx_buf=(unsigned long)tx,//transmitting buffer
.rx_buf= (unsigned long)rx,//recieving buffer
.len = ARRAY_SIZE(tx),//length of trasnmitting buffer
.delay_usecs=delay,
.speed_hz = speed,
.bits_per_word= bits,
};
ret = ioctl (fd, SPI_IOC_MESSAGE(1), &tr);//comm. is done by ioctl command, This initializes the transfer
for (ret=0;ret< ARRAY_SIZE(tx);ret++){//recieving the data in rx buffer and rx array size is same as tx array size
if (!(ret%4))//meant for printing process
puts("");
printf("%d\t %X\n",ret, rx[ret]);//formatting
}//herer return is used as an index for the recieving array
printf("\n");
float x=((rx[1]+rx[3])-(rx[0]+rx[2]))/(rx[0]+rx[1]+rx[2]+rx[3]);
//x[1]=((rx[5]+rx[7])-(rx[4])+rx[5])/(rx[4]+rx[5]+rx[6]+rx[7]);
printf("%f\n",x);
}//end of function for the transfer
/************************Main Program****************************************************************************************************************************/
int main(int argc, char *argv[]){// start of main
int ret=0;//initializing return
int fd;// a file handle to handle the device as a file
fd=open (device,O_RDWR);//fd handles this device with read and write permission
ret=ioctl(fd, SPI_IOC_WR_MODE,&mode);
ret=ioctl(fd, SPI_IOC_RD_MODE,&mode);
ret=ioctl(fd, SPI_IOC_WR_BITS_PER_WORD,&bits);
ret=ioctl(fd, SPI_IOC_RD_BITS_PER_WORD,&bits);
ret=ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ,&speed);
ret=ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ,&speed);
transfer(fd);//transfer of data begins
close(fd);//close the file handle, it has opened earlier
return ret;
}
I Just need my output with proper sign after calculation on the data.
Do you honestly think that how the data came into printf() matters? It really doesn't, printf() has no idea that you're using SPI, of course.
If all you want is the plus/minus to appear (instead of just the minus for negative values), reading the manual page for printf() tells us:
+
A sign (+ or -) should always be placed before a number produced by a signed conversion. By default a sign is used only for negative numbers. A + overrides a space if both are used.
So, you should use:
printf("%+d\t%+d\n", x[0], x[1]);
I need to free the processor while I wait for a change in the level of a GPIO pin (either rising or falling edge), so I created a simple code to poll a GPIO sysfs value file, but I'm running into some trouble:
In the first poll() call, it exits imediatelly, with both POLLPRI and POLLERR set in revents;
After this, I lseek() and read() the fd, and loop back to poll();
Now poll() hangs.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#include <sys/fcntl.h>
#define GPIO_DIR "/sys/class/gpio/"
#define GPIO_EXPORT GPIO_DIR "export"
int main(int argc, char **argv)
{
int gpio_fd;
struct pollfd gpio_fdset[1];
char pin_value[] = GPIO_DIR "gpioXYZ/value";
sprintf(pin_value, GPIO_DIR "gpio%s/value", argv[1]);
gpio_fd = open(pin_value, O_RDONLY);
while (1)
{
char buffer[64];
gpio_fdset[0].fd = gpio_fd;
gpio_fdset[0].events = POLLPRI;
gpio_fdset[0].revents = 0;
poll(gpio_fdset, 1, -1);
if (gpio_fdset[0].revents & POLLPRI)
{
printf("revents returned POLLPRI!\n");
lseek(gpio_fdset[0].fd, 0, SEEK_SET);
read(gpio_fdset[0].fd, buffer, 64);
}
}
}
Before calling it, I export the pin I wish to monitor (GPIO1_30 or 62 in the kernel numbering scheme). I've tried setting this pin as input, output, generating interrupts on rising and falling edges, but the behaviour is always the same. What am I missing?
From what I've read, when I use the sysfs, I should not need to use the gpio_request(), gpio_to_irq() and other related functions to be able to poll this pin. Is this right?
Regards,
Guilherme
I've discovered how to overcome this issue. Simply perform a dummy read() after setting opening the file descriptor. Apparently this is due to the fact that a recently opened fd is considered as changed (at least for GPIOs). As for the POLLERR on revents, this is standard sysfs behaviour.
If I understand your requirement right, then you want to take some action when the pin goes high.
you can poll the pin in application layer it self.
Download the "SimpleGPIO.h" and "SimpleGPIO.cpp" from the below URL:
https://github.com/derekmolloy/beaglebone
The SimpleGPIO.h/cpp is self explanatory and you can do all operations with GPIO using the simple function calls.
This one will work fine for any am335x processor. Then to poll you can use in your code some thing like this
int main()
{
//Your code
while(1)
{
if(gpio_get_value())
{
//Do what ever you want to do.
}
}
}
NOTE::
If you want to send any signal to your application process from kernel level using irq then the approach will be little different, But only for polling this code will work fine.
Hope this helps.
Edit:
Please refer below url for more details, it explains your question. You need to use any signal between (Signal number 32 to 64) to detect the change of GPIO status. You need to register your processId with your kernel module.
http://yongbingchen.github.io/blog/2013/03/11/sending-a-signal-from-linux-kernel/
When there is a change in GPIO status, Kernel sends a signal to application layer on which a dedicated function in application layer can execute.
I'm working on a new project where I want to make a connection with an FTDI which is connected to my debian machine. I am intending to write the code with C, not C++. Here lies my problem. All the examples I find are incomplete or are made for a c++ compiler in stead of the GCC compiler.
The goal is to talk to my microcontroller which is connected to the FTDI. For debugging i want to start building a linux application which is able to:
initialize a serial connection on startup with ttyUSB1
send a character string
display character strings when they are received by the pc
save the communication to a .txt file
Is there any example code or tutorial to make this?
If I succeed I will defenetly place the code here so that new viewers can use it to!
Edit:
Like I said I would post the code if I had it, and this is what worked for me:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#define MODEM "/dev/ttyUSB0"
#define BAUDRATE B115200
int main(int argc,char** argv)
{
struct termios tio;
struct termios stdio;
struct termios old_stdio;
int tty_fd, flags;
unsigned char c='D';
tcgetattr(STDOUT_FILENO,&old_stdio);
printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]);
memset(&stdio,0,sizeof(stdio));
stdio.c_iflag=0;
stdio.c_oflag=0;
stdio.c_cflag=0;
stdio.c_lflag=0;
stdio.c_cc[VMIN]=1;
stdio.c_cc[VTIME]=0;
tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // make the reads non-blocking
memset(&tio,0,sizeof(tio));
tio.c_iflag=0;
tio.c_oflag=0;
tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
tio.c_lflag=0;
tio.c_cc[VMIN]=1;
tio.c_cc[VTIME]=5;
if((tty_fd = open(MODEM , O_RDWR | O_NONBLOCK)) == -1){
printf("Error while opening\n"); // Just if you want user interface error control
return -1;
}
cfsetospeed(&tio,BAUDRATE);
cfsetispeed(&tio,BAUDRATE); // baudrate is declarated above
tcsetattr(tty_fd,TCSANOW,&tio);
while (c!='q'){
if (read(tty_fd,&c,1)>0){
write(STDOUT_FILENO,&c,1); // if new data is available on the serial port, print it out
printf("\n");
}
if (read(STDIN_FILENO,&c,1)>0){
write(tty_fd,&c,1);//if new data is available on the console, send it to serial port
printf("\n");
}
}
close(tty_fd);
tcsetattr(STDOUT_FILENO,TCSANOW,&old_stdio);
return EXIT_SUCCESS;
}
Most of the code came from http://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux but i also used a bit from the code posted below.
Handling with serial ports ( for linux OS ) :
- To open communication, you will need a descriptor which will be the handle for your serial port.
- Set the flags to control how the comunication will be.
- Write the command to this Handle ( make sure you're formatting the input correctly ).
- Get the answer. (make sure you're to read the amount of information you want )
- Close the handle.
It will seem like this:
int fd; // file descriptor
int flags; // communication flags
int rsl_len; // result size
char message[128]; // message to send, you can even dinamically alocate.
char result[128]; // result to read, same from above, thanks to #Lu
flags = O_RDWR | O_NOCTTY; // Read and write, and make the job control for portability
if ((fd = open("/dev/ttyUSB1", flags)) == -1 ) {
printf("Error while opening\n"); // Just if you want user interface error control
return -1;
}
// In this point your communication is already estabilished, lets send out something
strcpy(message, "Hello");
if (rsl_len = write(fd, message, strlen(message)) < 0 ) {
printf("Error while sending message\n"); // Again just in case
return -2;
}
if (rsl_len = read(fd, &result, sizeof(result)) < 0 ) {
printf("Error while reading return\n");
return -3;
}
close(fd);
Note that you have to care about what to write and what to read.
Some more flags can be used in case of parity control, stop bits, baud rate and more.
Since gcc is a C/C++ compiler, you don't need to limit yourself to pure C.
Sticking to pure C is OK if you enjoy writing lots of boilerplate code, and if you really know what you're doing. Many people use Unix APIs incorrectly, and a lot of example code out there is much too simplistic. Writing correct Unix C code is somewhat annoying, to say the least.
Personally, I'd suggest using not only C++, but also a higher-level application development framework like Qt. Qt 5 comes bundled with a QtSerialPort module that makes it easy to enumerate the serial ports, configure them, and get data into and out of them. Qt does not force you to use the gui modules, it can be a command line application, or a non-interactive server/daemon.
QtSerialPort is also usable from Qt 4, but it doesn't come bundled with Qt 4, you have to add it to your project. I suggest starting out with Qt 5, it's nicer to use with its C++11 support.
The code using Qt can be pretty simple, not much longer than your plain-English description. The below is a Qt console application using Qt 5 and C++11. It uses the core and serialport modules. It also handles the SIGINT signal so that the output file gets flushed before the process would terminate due to a ^C. I'm using QLocalSocket in place of raw Unix API to communicate from the Unix signal handler, the functionality is the same.
Only the code within main is strictly required, the rest is just to make it properly wrap things up when you hit ^C.
#include <QCoreApplication>
#include <QSerialPort>
#include <QFile>
#include <QTextStream>
#include <QLocalServer>
#include <QLocalSocket>
#include <cstdio>
#include <csignal>
QLocalSocket * xmit;
static void signalHandler(int)
{
xmit->write(" ");
xmit->flush();
}
static bool setupSignalHandler()
{
QLocalServer srv;
srv.listen("foobarbaz");
xmit = new QLocalSocket(qApp);
xmit->connectToServer(srv.serverName(), QIODevice::WriteOnly);
srv.waitForNewConnection();
QLocalSocket * receive = srv.nextPendingConnection();
receive->setParent(qApp);
qApp->connect(receive, &QLocalSocket::readyRead, &QCoreApplication::quit);
struct sigaction sig;
sig.sa_handler = signalHandler;
sigemptyset(&sig.sa_mask);
sig.sa_flags = SA_RESTART;
return ! sigaction(SIGINT, &sig, NULL);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
setupSignalHandler();
QSerialPort port("ttyUSB1");
QFile file("file.txt");
QTextStream err(stderr, QIODevice::WriteOnly);
QTextStream out(stdout, QIODevice::WriteOnly);
if (!file.open(QIODevice::WriteOnly)) {
err << "Couldn't open the output file" << endl;
return 1;
}
if (!port.open(QIODevice::ReadWrite)) {
err << "Couldn't open the port" << endl;
return 2;
}
port.setBaudRate(9600);
QObject::connect(&port, &QSerialPort::readyRead, [&](){
QByteArray data = port.readAll();
out << data;
file.write(data);
});
out << "Use ^C to quit" << endl;
return a.exec();
}
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.