Dear all,
I work with DM365 spectrum digital evaluation board.
I have to write device driver for UART on GPIO (Bit Bang), I all ready write the driver but during transmission , sometimes I get mistakes on the receive unit.
I check with oscilloscope, and I saw that sometimes dm365 transmits ~70usec delay (per bit) instead 52usec delay (per bit), and it destroy the character.
I think the problem is that, my driver in the low priority, and kernel leave the driver for a while, and come back after some time.
My question: how I can insure that kernel will not leave my driver during transmission character, I need to ensure .
The Transmit function: static void transmit_char(char data)
Thank
Alex
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/i2c/at24.h>
#include <linux/i2c/tsc2004.h>
#include <linux/leds.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/input.h>
#include <linux/spi/spi.h>
#include <linux/spi/eeprom.h>
#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 */
#include <linux/jiffies.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/mux.h>
#include <mach/hardware.h>
#include <mach/dm365.h>
#include <mach/psc.h>
#include <mach/common.h>
#include <mach/i2c.h>
#include <mach/serial.h>
#include <mach/mmc.h>
#include <mach/mux.h>
#include <mach/nand.h>
#include <mach/keyscan.h>
#include <mach/gpio.h>
#include <mach/cputype.h>
#include <linux/videodev2.h>
#include <media/tvp514x.h>
#include <media/tvp7002.h>
#include <media/davinci/videohd.h>
static void transmit_char(char data);
static int gpio1_open(struct inode *inode, struct file *filp);
static int gpio1_release(struct inode *inode, struct file *filp);
static ssize_t gpio1_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
static ssize_t gpio1_write(struct file *filp,const char __user *buf, size_t count, loff_t *f_pos);
static void gpio1_cleanup(void);
static int gpio1_init(void);
static void send_buffer(char *buffer, size_t count);
static char receive_func(void);
struct file_operations gpio1_fops = {
read: gpio1_read,
write: gpio1_write,
open: gpio1_open,
release: gpio1_release
};
/* Global variables of the driver */
/* Major number */
int memory_major = 60, buf_size;
/* Buffer to store data */
char *memory_buffer;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex D.");
static int io30 = 1;
module_param(io30, int,0);
static int io31 = 1;
module_param(io31, int,0);
static int io32 = 1;
module_param(io32, int,0);
static int io33 = 1;
module_param(io33, int,0);
#define bit_time 52 // usec ~= 1/19200(bits/sec)
#define bit_time_half 26
#define GPIO30_TXEN 30
#define GPIO31_TX 31
#define GPIO32_RXEN 32
#define GPIO33_RX 33
static int gpio1_open(struct inode *inode, struct file *filp) {
/* Success */
return 0;
}
static int gpio1_release(struct inode *inode, struct file *filp) {
/* Success */
return 0;
}
static ssize_t gpio1_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
}
static ssize_t gpio1_write( struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
printk("Hello Alex write\n");
copy_from_user(memory_buffer,buf,count);
send_buffer (memory_buffer,count);
return count;
}
static void dm365evm_DCMC_UART422_configure(void)
{
int ret = 0;
// davinci_cfg_reg(DM365_GPIO30_UART422_TXEN);
ret = gpio_request(30, "GPIO30_UART422_TXEN");
if (ret < 0) pr_warning("%s: gpio30-not good: %d\n",__func__, ret);
else pr_warning("%s: gpio30 good: %d\n",__func__, ret);
gpio_direction_output(30, 0);
// davinci_cfg_reg(DM365_GPIO31_UART422_TX);
ret = gpio_request(31, "GPIO31_UART422_TX");
if (ret < 0) pr_warning("%s: gpio31-no: %d\n",__func__, ret);
else pr_warning("%s: gpio31good: %d\n",__func__, ret);
gpio_direction_input(31);
// davinci_cfg_reg(DM365_GPIO32_UART422_RXEN);
ret = gpio_request(32, "GPIO32_UART422_RXEN");
if (ret < 0) pr_warning("%s: gpio32 no: %d\n",__func__, ret);
else pr_warning("%s: gpio32good: %d\n",__func__, ret);
gpio_direction_output(32,0);
// davinci_cfg_reg(DM365_GPIO33_UART422_RX);
// ret = gpio_request(33, "GPIO33_UART422_RX");
// if (ret < 0) pr_warning("%s: gpio33-no: %d\n",__func__, ret);
// else pr_warning("%s: gpio33good: %d\n", __func__, ret);
// gpio_direction_output(33, 0);
}
static void send_buffer(char *buffer, size_t count )
{
int i;
for(i=0; i<count; i++)
{
transmit_char(*buffer++);
mdelay(60);
}
}
static void loop_out(int loop)
{
int i=0;
for (i=0;i<loop;i++)
{
send_buffer("test",4);
mdelay(60);
}
}
static void transmit_char(char data)
{
// char temp=0;
char d0,d1,d2,d3,d4,d5,d6,d7;
d0= ((data) & 0x01) ;
d1= ((data >> 1) & 0x01);
d2= ((data >> 2) & 0x01);
d3= ((data >> 3) & 0x01);
d4= ((data >> 4) & 0x01);
d5= ((data >> 5) & 0x01);
d6= ((data >> 6) & 0x01);
d7= ((data >> 7) & 0x01);
gpio_set_value(GPIO32_RXEN,0); //start bit
udelay(bit_time);
// temp= ((data) & 0x01) ;
gpio_set_value(GPIO32_RXEN,d0);
udelay(bit_time);
// temp= ((data >> 1) & 0x01);
gpio_set_value(GPIO32_RXEN,d1);
udelay(bit_time);
// temp= ((data >> 2) & 0x01);
gpio_set_value(GPIO32_RXEN,d2);
udelay(bit_time);
// temp= ((data >> 3) & 0x01);
gpio_set_value(GPIO32_RXEN,d3);
udelay(bit_time);
// temp= ((data >> 4) & 0x01);
gpio_set_value(GPIO32_RXEN,d4);
udelay(bit_time);
// temp= ((temp) & 0x01);
gpio_set_value(GPIO32_RXEN,d5);
udelay(bit_time);
// temp= ((data >> 6) & 0x01);
gpio_set_value(GPIO32_RXEN,d6);
udelay(bit_time);
// temp= ((data >> 7) & 0x01);
gpio_set_value(GPIO32_RXEN,d7);
udelay(bit_time);
gpio_set_value(GPIO32_RXEN,1); // stop bit
udelay(bit_time);
}
static char receive_func(void)
{
char result=0, temp=0;
// if (gpio_get_value(GPIO30_TXEN)==0) //start bit
// {
udelay(bit_time);
udelay(bit_time_half);
temp=gpio_get_value(GPIO30_TXEN); //1st bit
result=0x01&(temp);
udelay(bit_time);
temp=gpio_get_value(GPIO30_TXEN); //2nd bit
temp=(0x01&(temp));
result=result|(temp<<1);
udelay(bit_time);
temp=gpio_get_value(GPIO30_TXEN); //3rd bit
temp=(0x01&(temp));
result=result|(temp<<2);
udelay(bit_time);
temp=gpio_get_value(GPIO30_TXEN); //4th bit
temp=(0x01&(temp));
result=result|(temp<<3);
udelay(bit_time);
temp=gpio_get_value(GPIO30_TXEN); //5 bit
temp=(0x01&(temp));
result=result|(temp<<4);
udelay(bit_time);
temp=gpio_get_value(GPIO30_TXEN); //6 bit
temp=(0x01&(temp));
result=result|(temp<<5);
udelay(bit_time);
temp=gpio_get_value(GPIO30_TXEN); //7 bit
temp=(0x01&(temp));
result=result|(temp<<6);
udelay(bit_time);
temp=gpio_get_value(GPIO30_TXEN); //8 bit
temp=(0x01&(temp));
result=result|(temp<<7);
// }
return result;
}
static int gpio1_init(void)
{
int result;
/* Registering device */
result = register_chrdev(memory_major, "memory", &gpio1_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(8192, GFP_USER);
buf_size = 8192;
if (!memory_buffer) {
result = -ENOMEM;
printk("memory alloc fail\n");
goto fail;
}
memset(memory_buffer, 0, 1);
printk("<1>Inserting memory module\n");
printk("Hello,this is gpio 1st code\n");
//dm365evm_DCMC_UART422_configure();
loop_out(10);
return 0;
fail:
gpio1_cleanup();
return result;
}
static void gpio1_cleanup(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");
printk("Exit Gpio Module\n");
gpio_free(30);
gpio_free(31);
gpio_free(32);
// gpio_free(33);
}
module_init(gpio1_init);
module_exit(gpio1_cleanup);