Defining buffer size in Linux kernel module by parameter - size

I need to change the buffer size in the character device by parameter, so that, for example, when I write
insmod chardev.ko len=6
echo "Have a nice day!" > /dev/chardev.ko
cat /dev/chardev.ko
My output would be:
Have a
I've simply tried to replace the msg[BUF_SIZE] by msg[len], but I receive an error 'variably modified at file scope'.
I have no idea how to proceed. Any hints?
Here's the code:
/*
* chardev.c: Creates a read-only char device that says how many times
* you've read from the dev file
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h> /* for put_user */
/*
* Prototypes - this would normally go in a .h file
*/
int init_module(void);
void cleanup_module(void);
static int device_open(struct inode *, struct file *);
static int device_release(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 int len=100;
module_param(len, int, S_IRUGO);
MODULE_PARM_DESC(len, "The length of buffer");
#define SUCCESS 0
#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices */
#define BUF_LEN 100
/*
* Global variables are declared as static, so are global within the file.
*/
static int Major; /* Major number assigned to our device driver */
static int Device_Open = 0; /* Is device open?
* Used to prevent multiple access to device */
static char msg[BUF_LEN]; /* The msg the device will give when asked */
static char *msg_Ptr;
static struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
/*
* This function is called when the module is loaded
*/
int init_module(void)
{
Major = register_chrdev(0, DEVICE_NAME, &fops);
if (Major < 0) {
printk(KERN_ALERT "Registering char device failed with %d\n", Major);
return Major;
}
printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major);
printk(KERN_INFO "the driver, create a dev file with\n");
printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);
// minor numbers are used to differentiate multiple instances of a
// device that use the same driver.
printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n");
printk(KERN_INFO "the device file.\n");
printk(KERN_INFO "Remove the device file and module when done.\n");
return SUCCESS;
}
/*
* This function is called when the module is unloaded
*/
void cleanup_module(void)
{
/*
* Unregister the device
*/
#if 0
int ret = unregister_chrdev(Major, DEVICE_NAME);
if (ret < 0)
printk(KERN_ALERT "Error in unregister_chrdev: %d\n", ret);
#endif
unregister_chrdev(Major, DEVICE_NAME);
}
/*
* Methods
*/
/*
* Called when a process tries to open the device file, like
* "cat /dev/mycharfile"
*/
static int device_open(struct inode *inode, struct file *file)
{
static int counter = 0;
if (Device_Open)
return -EBUSY;
Device_Open++;
sprintf(msg, "I already told you %d times Hello world!\n", counter++);
msg_Ptr = msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
/*
* Called when a process closes the device file.
*/
static int device_release(struct inode *inode, struct file *file)
{
Device_Open--; /* We're now ready for our next caller */
/*
* Decrement the usage count, or else once you opened the file, you'll
* never get get rid of the module.
*/
module_put(THIS_MODULE);
return 0;
}
/*
* Called when a process, which already opened the dev file, attempts to
* read from it.
*/
static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */
char *buffer, /* buffer to fill with data */
size_t length, /* length of the buffer */
loff_t * offset)
{
/*
* Number of bytes actually written to the buffer
*/
int bytes_read = 0;
/*
* If we're at the end of the message,
* return 0 signifying end of file
*/
if (*msg_Ptr == 0)
return 0;
/*
* Actually put the data into the buffer
*/
while (length && *msg_Ptr) {
/*
* The buffer is in the user data segment, not the kernel
* segment so "*" assignment won't work. We have to use
* put_user which copies data from the kernel data segment to
* the user data segment.
*/
put_user(*(msg_Ptr++), buffer++);
length--;
bytes_read++;
}
/*
* Most read functions return the number of bytes put into the buffer
*/
return bytes_read;
}
/*
* Called when a process writes to dev file: echo "hi" > /dev/hello
*/
static ssize_t
device_write(struct file *filp, const char *buffer, size_t length, loff_t * off)
{
int i;
#ifdef DEBUG
printk(KERN_INFO "device_write(%p,%s,%d", file, buffer, length)
#endif // DEBUG
for(i=0; (i<length && i<BUF_LEN) || i<len; i++)
{
get_user(msg[i], buffer+i);
}
msg_Ptr=msg;
return i;
}
https://pastebin.com/wQP9p42G
Thanks in advance!

Related

avr codevision issue getting acknowledge or TX_DS flag in nRF24L01+ MODULE

I am trying to communicate using two nRF24L01 radio modules connected to atmega8s over spi.
All I can do is to write some register of the nRF, but no data can be sent. When I read the radio status register it returns decimal 14 or sometimes 0 or sometimes decimal 30.
Here is my atmega8 code:
#include <mega8.h>
#include <C:\cvavr\BIN\nRF24L01\nrf24l012.h>
#include <stdio.h>
#include <pcf8576d.h>
#define _CH 1 // Channel 0..125
#define _Address_Width 5 // 3..5
#define _Buffer_Size 32 // 1..32
// Declare your global variables here
unsigned char global_var=0;
void NRF24L01_Receive(char Buf[_Buffer_Size]) {
NRF24L01_CE_HIGH;
delay_us(130);
while ((NRF24L01_Get_Status() & _RX_DR) != _RX_DR);
NRF24L01_CE_LOW;
NRF24L01_Read_RX_Buf(Buf, _Buffer_Size);
NRF24L01_Clear_Interrupts();
}
void NRF24L01_Send(char* Buf) {
NRF24L01_Write_TX_Buf(Buf, _Buffer_Size);
NRF24L01_RF_TX();
while ((NRF24L01_Get_Status() & _TX_DS) != _TX_DS) ;
NRF24L01_Clear_Interrupts();
}
// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
char buffer[32];
char state = NRF24L01_Get_Status();
lcd_erase();
lcd_printf("INT ");
lcd_print(state);
if(state==0) NRF24L01_Read_RX_Buf(buffer,32);
lcd_print(buffer[0]);
delay_ms(100);
NRF24L01_Clear_Interrupts();
}
// SPI interrupt service routine
interrupt [SPI_STC] void spi_isr(void)
{
}
void main(void)
{
// Declare your local variables here
char i;
unsigned char bffr[5];
unsigned char Buf[_Buffer_Size];
unsigned char Data[5]={3,9,5,8,4};
unsigned char Address_p0[_Address_Width] = { 0xf0,0xf0,0xf0,0xf0,0xe1 };
unsigned char Address_p1[_Address_Width] = { 0xf0,0xf0,0xf0,0xf0,0xd2 };
unsigned char Address_p2[1]={0xc3};
unsigned char Address_p3[1]={0xc4};
unsigned char Address_p4[1]={0xc5};
unsigned char Address_p5[1]={0xc6};
spi_int1_init();
TWI_init_master();
delay_ms(300);
lcd_erase();
lcd_printf("start");
delay_ms(1200);
NRF24L01_Init(_TX_MODE, _CH, _1Mbps, Address_p0, _Address_Width, _Buffer_Size);
NRF24L01_WriteReg(W_REGISTER | EN_RXADDR,0x03);
NRF24L01_Set_RX_Pipe (0,Address_p0,_Address_Width, _Buffer_Size);
NRF24L01_Set_RX_Pipe (1,Address_p1,_Address_Width, _Buffer_Size);
NRF24L01_Set_TX_Address(Address_p0,_Address_Width);
NRF24L01_Set_RX_Pipe (2,Address_p2,1,0);
NRF24L01_Set_RX_Pipe (3,Address_p3,1,0);
NRF24L01_Set_RX_Pipe (4,Address_p4,1,0);
NRF24L01_Set_RX_Pipe (5,Address_p5,1,0);
NRF24L01_WriteReg(W_REGISTER | EN_AA,0X3F);
NRF24L01_WriteReg(W_REGISTER | EN_RXADDR,0x03);
NRF24L01_WriteReg(W_REGISTER | RF_CH, 0x0c);
NRF24L01_WriteReg(W_REGISTER | RF_SETUP,0X03);
NRF24L01_WriteReg(W_REGISTER | CONFIG,0X0E);
NRF24L01_WriteReg(W_REGISTER | SETUP_RETR,0X28);
global_var = NRF24L01_Get_Status();
//global_var=SPI(234);
lcd_erase();
lcd_print(global_var);
delay_ms(1000);
global_var = NRF24L01_ReadReg(CONFIG);
lcd_erase();
lcd_print(global_var);
delay_ms(1000);
lcd_erase();
NRF24L01_ReadRegBuf(TX_ADDR,bffr,5);
for(i=0;i<5;i++)
lcd_print(bffr[i]);
delay_ms(1000);
global_var = NRF24L01_ReadReg(FIFO_STATUS);
lcd_erase();
lcd_printf("ffo ");
lcd_print(global_var);
delay_ms(1000);
NRF24L01_Send(Data);
global_var = NRF24L01_Get_Status();
lcd_erase();
lcd_print(global_var);
delay_ms(1000);
global_var = NRF24L01_ReadReg(FIFO_STATUS);
lcd_erase();
lcd_printf("mioh ");
lcd_print(global_var);
delay_ms(1000);
while (1);
}
and here is my nrf24l012.h
#include <delay.h>
#include <C:\cvavr\BIN\nRF24L01\nrf24l011.h>
/*
* SPI pins:
* MOSI: DDB3
* MISO: DDB4
* SCK : DDB5
* CSN : DDB2
* CE : DDB1
*/
void spi_int1_init(void){
// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=Out Bit4=In Bit3=Out Bit2=Out Bit1=In Bit0=In
DDRB=(0<<DDB7) | (0<<DDB6) | (1<<DDB5) | (0<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=0 Bit4=T Bit3=0 Bit2=0 Bit1=T Bit0=T
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
// External Interrupt(s) initialization
// INT0: Off
// INT1: On
// INT1 Mode: Falling Edge
GICR|=(1<<INT1) | (0<<INT0);
MCUCR=(1<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
GIFR=(1<<INTF1) | (0<<INTF0);
// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 2000.000 kHz
// SPI Clock Phase: Cycle Start
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=(1<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);
SPSR=(0<<SPI2X);
// Clear the SPI interrupt flag
#asm
in r30,spsr
in r30,spdr
#endasm
// Global enable interrupts
#asm("sei")
}
//Function to send and receive data for both master and slave
unsigned char SPI(unsigned char data)
{
// Load data into the buffer
SPDR = data;
//Wait until transmission complete
while(!(SPSR & (1<<SPIF) ));
SPSR = (1<<SPIF);
// Return received data
return(SPDR);
}
/* CE is set to output */
#define NRF24L01_CE_OUT DDRB |= (1<<DDB1) ;
#define NRF24L01_CE_HIGH PORTB |= (1<<DDB1) ;
#define NRF24L01_CE_LOW PORTB &= ~(1<<DDB1);
#define NRF24L01_CSN_HIGH PORTB |= (1<<DDB2) ;
#define NRF24L01_CSN_LOW PORTB &= ~(1<<DDB2);
/**
Read a register
#param Reg Register to read
#return Registry Value
*/
char NRF24L01_ReadReg(char Reg) {
char Result;
NRF24L01_CSN_LOW;
SPI(Reg);
Result = SPI(NOP); // "NOP" in here just roles as a dummy data byte nothing more.
NRF24L01_CSN_HIGH;
return Result;
}
/**
Returns the STATUS register and then modify a register
#param Reg Register to change
#param Value New value
#return STATUS Register
*/
char NRF24L01_WriteReg(char Reg, char Value) {
char Result;
NRF24L01_CSN_LOW;
Result = SPI(Reg);
SPI(Value);
NRF24L01_CSN_HIGH;
return Result;
}
/**
Returns the STATUS register and then read "n" registers
#param Reg Register to read
#param Buf Pointer to a buffer
#param Size Buffer Size
#return STATUS Register
*/
char NRF24L01_ReadRegBuf(char Reg, char *Buf, int Size) {
int i;
char Result;
NRF24L01_CSN_LOW;
Result = SPI(Reg);
for (i = 0; i < Size; i++) {
Buf[i] = SPI(NOP);
}
NRF24L01_CSN_HIGH;
return Result;
}
/**
Returns the STATUS register and then write "n" registers
#param Reg Registers to change
#param Buf Pointer to a buffer
#param Size Buffer Size
#return STATUS Register
*/
char NRF24L01_WriteRegBuf(char Reg, char *Buf, int Size) {
int i;
char Result;
NRF24L01_CSN_LOW;
Result = SPI(Reg);
for (i = 0; i < Size; i++) {
SPI(Buf[i]);
}
NRF24L01_CSN_HIGH;
return Result;
}
/**
Returns the STATUS register
#return STATUS Register
*/
char NRF24L01_Get_Status(void) {
char Result;
NRF24L01_CSN_LOW;
Result = SPI(NOP);
NRF24L01_CSN_HIGH;
return Result;
}
/**
Returns the carrier signal in RX mode (high when detected)
#return CD
*/
char NRF24L01_Get_CD(void) {
return (NRF24L01_ReadReg(CD) & 1);
}
/**
Select power mode
#param Mode = _POWER_DOWN, _POWER_UP
#see _POWER_DOWN
#see _POWER_UP
*/
void NRF24L01_Set_Power(char Mode) {
char Result;
Result = NRF24L01_ReadReg(CONFIG) & 0b01111101; // Read Conf. Reg. AND Clear bit 1 (PWR_UP) and 7 (Reserved)
NRF24L01_WriteReg(W_REGISTER | CONFIG, Result | Mode);
}
/**
Select the radio channel
#param CH = 0..125
*/
void NRF24L01_Set_CH(char CH) {
NRF24L01_WriteReg(W_REGISTER | RF_CH, (CH & 0b01111111)); // Clear bit 8
}
/**
Select Enhanced ShockBurst ON/OFF
Disable this functionality to be compatible with nRF2401
#param Mode = _ShockBurst_ON, _ShockBurst_OFF
#see _ShockBurst_ON
#see _ShockBurst_OFF
*/
void NRF24L01_Set_ShockBurst(char Mode) {
NRF24L01_WriteReg(W_REGISTER | SETUP_RETR, Mode);
NRF24L01_WriteReg(W_REGISTER | EN_AA, Mode);
}
/**
Select the address width
#param Width = 3..5
*/
void NRF24L01_Set_Address_Width(char Width) {
NRF24L01_WriteReg(W_REGISTER | SETUP_AW, (Width - 2)); // orginal was (Width & 3) -2) but is incorrect
}
/**
Select mode receiver or transmitter
#param Device_Mode = _TX_MODE, _RX_MODE
#see _TX_MODE
#see _RX_MODE
*/
void NRF24L01_Set_Device_Mode(char Device_Mode) {
char Result;
Result = NRF24L01_ReadReg(CONFIG) & 0b01111110; // Read Conf. Reg. AND Clear bit 0 (PRIM_RX) and 7 (Reserved)
NRF24L01_WriteReg(W_REGISTER | CONFIG, Result | Device_Mode);
}
/**
Enables and configures the pipe receiving the data
#param PipeNum Number of pipe
#param Address Address
#param AddressSize Address size
#param PayloadSize Buffer size, data receiver
*/
void NRF24L01_Set_RX_Pipe(char PipeNum, char *Address, int AddressSize, char PayloadSize) {
char Result;
Result = NRF24L01_ReadReg(EN_RXADDR);
NRF24L01_WriteReg(W_REGISTER | EN_RXADDR, Result | (1 << PipeNum));
NRF24L01_WriteReg(W_REGISTER | (RX_PW_P0 + PipeNum), PayloadSize);
NRF24L01_WriteRegBuf(W_REGISTER | (RX_ADDR_P0 + PipeNum), Address, AddressSize);
}
/**
Disable all pipes
*/
void NRF24L01_Disable_All_Pipes(void) {
NRF24L01_WriteReg(W_REGISTER | EN_RXADDR, 0);
}
/** Returns the STATUS register and then clear all interrupts
*
* #return STATUS Register
*/
char NRF24L01_Clear_Interrupts(void) {
return NRF24L01_WriteReg(W_REGISTER | STATUS, _RX_DR | _TX_DS | _MAX_RT);
}
/**
Sets the direction of transmission
#param Address Address
#param Size Address size 3..5
*/
void NRF24L01_Set_TX_Address(char *Address, int Size) {
NRF24L01_WriteRegBuf(W_REGISTER | TX_ADDR, Address, Size);
}
/**
Empty the transmit buffer
*/
void NRF24L01_Flush_TX(void) {
NRF24L01_CSN_LOW;
SPI(FLUSH_TX);
NRF24L01_CSN_HIGH;
}
/**
Empty the receive buffer
*/
void NRF24L01_Flush_RX(void) {
NRF24L01_CSN_LOW;
SPI(FLUSH_RX);
NRF24L01_CSN_HIGH;
}
/**
Initializes the device
#param Device_Mode = _TX_MODE, _RX_MODE
#param CH = 0..125
#param DataRate = _1Mbps, _2Mbps
#param Address Address
#param Address_Width Width direction: 3..5
#param Size_Payload Data buffer size
#see _TX_MODE
#see _RX_MODE
#see _1Mbps
#see _2Mbps
*/
void NRF24L01_Init(char Device_Mode, char CH, char DataRate,
char *Address, char Address_Width, char Size_Payload) {
NRF24L01_CE_OUT; // Set Port DIR out
// Enable Enhanced ShockBurst....._ShockBurst_OFF
NRF24L01_Set_ShockBurst(_ShockBurst_ON);
// RF output power in TX mode = 0dBm (Max.)
// Set LNA gain
NRF24L01_WriteReg(W_REGISTER | RF_SETUP, 0b00000111 | DataRate);
NRF24L01_Set_Address_Width(Address_Width);
NRF24L01_Set_RX_Pipe(0, Address, Address_Width, Size_Payload);
NRF24L01_Set_CH(CH);
NRF24L01_Set_TX_Address(Address, Address_Width); // Set Transmit address
// Bits 4..6: Reflect interrupts as active low on the IRQ pin
// Bit 3: Enable CRC
// Bit 2: CRC 1 Byte
// Bit 1: Power Up
NRF24L01_WriteReg(W_REGISTER | CONFIG, 0b00001010 | Device_Mode);
delay_us(1500);
}
/**
Turn on transmitter, and transmits the data loaded into the buffer
*/
void NRF24L01_RF_TX(void) {
NRF24L01_CE_LOW;
NRF24L01_CE_HIGH;
delay_us(10);
NRF24L01_CE_LOW;
}
/**
Writes the buffer of data transmission
#param Buf Buffer with data to send
#param Size Buffer size
*/
void NRF24L01_Write_TX_Buf(char *Buf, int Size) {
NRF24L01_WriteRegBuf(W_REGISTER | W_TX_PAYLOAD, Buf, Size);
}
/**
Read the data reception buffer
#param Buf Buffer with data received
#param Size Buffer size
*/
void NRF24L01_Read_RX_Buf(char *Buf, int Size) {
NRF24L01_ReadRegBuf(R_RX_PAYLOAD, Buf, Size);
}
i can not understand what is the problem..
please help me thanks?!
AND HERE IS nrf24l01+.h definition
/*
* #author
* Copyright (C) 2012 Luis R. Hilario http://www.luisdigital.com
*
*/
// Bits
/**
* Data Ready RX FIFO interrupt
*/
#define _RX_DR (1<<6)
/**
* Data Sent TX FIFO interrupt
*/
#define _TX_DS (1<<5)
/**
* Maximum number of TX retransmits interrupt
*/
#define _MAX_RT (1<<4)
/** Power Down mode
*
* Minimal current consumption, SPI can be activated
*
* #see NRF24L01_Set_Power(char Mode)
*/
#define _POWER_DOWN 0
/** Power Up mode
*
* Standby-I mode
*
* #see NRF24L01_Set_Power(char Mode)
*/
#define _POWER_UP (1<<1)
/** Mode radio transmitter
*
* #see NRF24L01_Set_Device_Mode(char Device_Mode)
* #see NRF24L01_Init(char Device_Mode, char CH, char DataRate,
char *Address, char Address_Width, char Size_Payload)
*/
#define _TX_MODE 0
/** Mode radio receiver
*
* #see NRF24L01_Set_Device_Mode(char Device_Mode)
* #see NRF24L01_Init(char Device_Mode, char CH, char DataRate,
char *Address, char Address_Width, char Size_Payload)
*/
#define _RX_MODE 1
/** Air data rate = 1 Mbps
*
*
* #see NRF24L01_Init(char Device_Mode, char CH, char DataRate,
char *Address, char Address_Width, char Size_Payload)
*/
#define _1Mbps 0
/** Air data rate = 2 Mbps
*
* #see NRF24L01_Init(char Device_Mode, char CH, char DataRate,
char *Address, char Address_Width, char Size_Payload)
*/
#define _2Mbps (1<<3)
/** Enable ShockBurst
Automatic Retransmission (Up to 1 Re-Transmit on fail of AA)
Auto Acknowledgment (data pipe 0)
#see NRF24L01_Set_ShockBurst(char Mode)
*/
#define _ShockBurst_ON 1
/** Disable ShockBurst
*
#see NRF24L01_Set_ShockBurst(char Mode)
*/
#define _ShockBurst_OFF 0
// REGISTERS
#define CONFIG 0x00
#define EN_AA 0x01
#define EN_RXADDR 0x02
#define SETUP_AW 0x03
#define SETUP_RETR 0x04
#define RF_CH 0x05
#define RF_SETUP 0x06
#define STATUS 0x07
#define OBSERVE_TX 0x08
#define CD 0x09
#define RX_ADDR_P0 0x0A
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
#define DYNPD 0x1C
#define FEATURE 0x1D
// COMMANDS
#define R_REGISTER 0x00
#define W_REGISTER 0x20
#define R_RX_PAYLOAD 0x61
#define W_TX_PAYLOAD 0xA0
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define ACTIVATE 0x50
#define R_RX_PL_WID 0x60
#define W_ACK_PAYLOAD 0xA8
#define W_TX_PAYLOAD_NOACK 0x58
#define NOP 0xFF
/*
* SPI functions for NRF24L01
*/
char NRF24L01_ReadReg(char Reg);
char NRF24L01_WriteReg(char Reg, char Value);
char NRF24L01_ReadRegBuf(char Reg, char *Buf, int Size);
char NRF24L01_WriteRegBuf(char Reg, char *Buf, int Size);
/*
* NRF24L01 functions
*/
char NRF24L01_Get_Status(void);
char NRF24L01_Get_CD(void);
void NRF24L01_Set_Power(char Mode);
void NRF24L01_Set_CH(char CH);
void NRF24L01_Set_ShockBurst(char Mode);
void NRF24L01_Set_Address_Width(char Width);
void NRF24L01_Set_Device_Mode(char Device_Mode);
void NRF24L01_Set_RX_Pipe(char PipeNum, char *Address, int AddressSize, char PayloadSize);
void NRF24L01_Disable_All_Pipes(void);
char NRF24L01_Clear_Interrupts(void);
void NRF24L01_Set_TX_Address(char *Address, int Size);
void NRF24L01_Flush_TX(void);
void NRF24L01_Flush_RX(void);
void NRF24L01_Init(char Device_Mode, char CH, char DataRate,
char *Address, char Address_Width, char Size_Payload);
void NRF24L01_RF_TX(void);
void NRF24L01_Write_TX_Buf(char *Buf, int Size);
void NRF24L01_Read_RX_Buf(char *Buf, int Size);
hello friends succesfully i get it and i was able to send data over nrf24l01+ module to another nrf24l01+ module for this i used an ATMEGA16A as TX and an ATmega8a as RX(receiver) controller:
i used the code in this link written by some good people and it works perfectly but i need to change som i/o port to be compitable with Atmega8 for receiver module .
as i compare my last code with this one i understand that i changed rx and tx Adresses and in this code (works well) nothing is changed related to Adresses of module and left to its default values..
so my fault was manipulating adresses incorrectly..
here is the link to code works good..
UPDATE: as i revisited my code to see whats problem i understand the whole problem was from nrf24l01.h file that declared a function misdingushly it sends W_TX_PAYLOAD ORing with W_REGISTER while such an adress is not exist in nrf so the whole process is got wrong..
error was in declaring :
'NRF24L01_Write_TX_Buf ' function
in line:
NRF24L01_WriteRegBuf(W_REGISTER | W_TX_PAYLOAD, Buf, Size);
while this is wrong and must be Corrected as:
NRF24L01_WriteRegBuf(W_TX_PAYLOAD, Buf, Size);
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
http://www.avrfreaks.net/forum/nrf24l01-problem-communication-failure-cannot-even-read-registers-data-atmega16a

wolfSSL_read() returns 0

I am using Microsoft Visual Studio 2010 and wolfSSL 3.7.0.
I create server context with these functions:
WOLFSSL_CTX *sslContext = wolfSSL_CTX_new(wolfTLSv1_2_server_method());
if(!sslContext)
{
closesocket(socketListen);
return FALSE;
}
wolfSSL_CTX_use_certificate_buffer(sslContext, (unsigned char*)szServerCert, strlen(szServerCert), SSL_FILETYPE_PEM);
wolfSSL_CTX_use_PrivateKey_buffer(sslContext, (unsigned char*)szServerKey, strlen(szServerKey), SSL_FILETYPE_PEM);
It is OK. Then, I accept the connection, create WOLFSSL* context and associate it with my socket descriptor:
WOLFSSL *ssl = wolfSSL_new(sslContext);
wolfSSL_set_fd(ssl, Socket);
CHAR Buffer[1024];
int retVal = wolfSSL_read(ssl, Buffer, 1024);
But when I try to connect to 127.0.0.1:443 via browser, wolfSSL_read() returns 0. wolfSSL_get_error() returns -397 (SOCKET_PEER_CLOSED_E). Browser shows me that page is still loading. What is the reason?
wolfSSL provides a good reference example here: https://github.com/wolfSSL/wolfssl-examples/blob/master/tls/server-tls.c
Please find referenced code below:
/* server-tls.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*=============================================================================
*
* This is a super basic example of what a TCP Server secured with TLS 1.2
* might look like. This server can also resume the session if a client
* inadvertantly disconnects.
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
/* include the wolfSSL library for our TLS 1.2 security */
#include <wolfssl/ssl.h>
#define DEFAULT_PORT 11111
int AcceptAndRead(WOLFSSL_CTX* ctx, socklen_t sockfd, struct sockaddr_in
clientAddr);
int AcceptAndRead(WOLFSSL_CTX* ctx, socklen_t sockfd, struct sockaddr_in
clientAddr)
{
/* Create our reply message */
const char reply[] = "I hear ya fa shizzle!\n";
socklen_t size = sizeof(clientAddr);
/* Wait until a client connects */
socklen_t connd = accept(sockfd, (struct sockaddr *)&clientAddr, &size);
/* If fails to connect,int loop back up and wait for a new connection */
if (connd == -1) {
printf("failed to accept the connection..\n");
}
/* If it connects, read in and reply to the client */
else {
printf("Client connected successfully\n");
WOLFSSL* ssl;
if ( (ssl = wolfSSL_new(ctx)) == NULL) {
fprintf(stderr, "wolfSSL_new error.\n");
exit(EXIT_FAILURE);
}
/* direct our ssl to our clients connection */
wolfSSL_set_fd(ssl, connd);
printf("Using Non-Blocking I/O: %d\n", wolfSSL_get_using_nonblock(
ssl));
for ( ; ; ) {
char buff[256];
int ret = 0;
/* Clear the buffer memory for anything possibly left over */
memset(&buff, 0, sizeof(buff));
/* Read the client data into our buff array */
if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) > 0) {
/* Print any data the client sends to the console */
printf("Client: %s\n", buff);
/* Reply back to the client */
if ((ret = wolfSSL_write(ssl, reply, sizeof(reply)-1))
< 0)
{
printf("wolfSSL_write error = %d\n", wolfSSL_get_error(ssl, ret));
}
}
/* if the client disconnects break the loop */
else {
if (ret < 0)
printf("wolfSSL_read error = %d\n", wolfSSL_get_error(ssl
,ret));
else if (ret == 0)
printf("The client has closed the connection.\n");
break;
}
}
wolfSSL_free(ssl); /* Free the WOLFSSL object */
}
close(connd); /* close the connected socket */
return 0;
}
int main()
{
/* Create a ctx pointer for our ssl */
WOLFSSL_CTX* ctx;
/*
* Creates a socket that uses an internet IP address,
* Sets the type to be Stream based (TCP),
* 0 means choose the default protocol.
*/
socklen_t sockfd = socket(AF_INET, SOCK_STREAM, 0);
int loopExit = 0; /* 0 = False, 1 = True */
int ret = 0; /* Return value */
/* Server and client socket address structures */
struct sockaddr_in serverAddr = {0}, clientAddr = {0};
/* Initialize wolfSSL */
wolfSSL_Init();
/* If positive value, the socket is valid */
if (sockfd == -1) {
printf("ERROR: failed to create the socket\n");
return EXIT_FAILURE; /* Kill the server with exit status 1 */
}
/* create and initialize WOLFSSL_CTX structure */
if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())) == NULL) {
fprintf(stderr, "wolfSSL_CTX_new error.\n");
return EXIT_FAILURE;
}
/* Load server certificate into WOLFSSL_CTX */
if (wolfSSL_CTX_use_certificate_file(ctx, "../certs/server-cert.pem",
SSL_FILETYPE_PEM) != SSL_SUCCESS) {
fprintf(stderr, "Error loading certs/server-cert.pem, please check"
"the file.\n");
return EXIT_FAILURE;
}
/* Load server key into WOLFSSL_CTX */
if (wolfSSL_CTX_use_PrivateKey_file(ctx, "../certs/server-key.pem",
SSL_FILETYPE_PEM) != SSL_SUCCESS) {
fprintf(stderr, "Error loading certs/server-key.pem, please check"
"the file.\n");
return EXIT_FAILURE;
}
/* load DH params */
ret = wolfSSL_CTX_SetTmpDH_file(ctx, "../certs/dh2048.pem" , SSL_FILETYPE_PEM);
if (ret != SSL_SUCCESS) {
fprintf(stderr, "Error setting DH parameters.\n");
return EXIT_FAILURE;
}
/* Initialize the server address struct to zero */
memset((char *)&serverAddr, 0, sizeof(serverAddr));
/* Fill the server's address family */
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(DEFAULT_PORT);
/* Attach the server socket to our port */
if (bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr))
< 0) {
printf("ERROR: failed to bind\n");
return EXIT_FAILURE;
}
printf("Waiting for a connection...\n");
/* Continuously accept connects while not currently in an active connection
or told to quit */
while (loopExit == 0) {
/* listen for a new connection, allow 5 pending connections */
ret = listen(sockfd, 5);
if (ret == 0) {
/* Accept client connections and read from them */
loopExit = AcceptAndRead(ctx, sockfd, clientAddr);
}
}
wolfSSL_CTX_free(ctx); /* Free WOLFSSL_CTX */
wolfSSL_Cleanup(); /* Free wolfSSL */
return EXIT_SUCCESS;
}

how to print all the vxWorks wvEvents

Is there a vxWorks command that lists all the wv events that are compiled in the code. I am trying to segregate all the events on one of our products which uses vxWorks 6.5.
No there isn't a command giving you a list of WindView events of your code.
Why don't you search for all lines containing wvEvent of all your source files and remove the duplicates? This should produce a list of all events...
--- Update ---
I've written the following small library to hook symbols within the VxWorks symbol table. This can be used to hook system calls within applications loaded after a symbol was hooked.
The following mechanism works since the ld command resolves all unresolved references of the application using the system symbol table (e.g. calls to printf are replaced with the value of the symbol printf which is the address of the printf implementation).
Here is the code of the library:
#include <vxWorks.h>
#include <symLib.h>
#define MAX_HOOKS 256
typedef struct vxhook_struct
{
SYMTAB_ID symTblId; /** id of symbol table containing the symbol */
SYMBOL *symbol; /** pointer to symbol entry within symbol table */
void *originalValue; /** original value of symbol */
void *hookedValue; /** hooked value of symbol */
} VXHOOK;
/** counter of installed hooks */
static int hooks = 0;
/** list of installed hooks */
static VXHOOK hook[MAX_HOOKS];
/*
** symbolIterator
** VxWorks callback for symbol table iteration. See symEach(..) for more information.
*/
static BOOL symbolIterator(char *name,
int val,
SYM_TYPE type,
int arg,
UINT16 group)
{
BOOL result = TRUE; /* continue iteration */
char *pName;
pName = (char *)arg;
if ((pName != NULL) && (name != NULL))
{
if (!strcmp(name, pName))
{
result = FALSE; /* symbol found => stop iteration! */
}
}
return (result);
}
/*
** vxHookGet
** Searches the hook list for a specific entry and returns a pointer to it if found.
*/
static VXHOOK *vxHookGet(SYMTAB_ID symTblId, /* symbol table to seachr for name */
char *name, /* name of symbol */
int *index) /* optional return value of index within hook list */
{
VXHOOK *pHook = NULL;
int i;
if (index != NULL)
{
*index = -1;
}
for (i = 0; i < hooks; i++)
{
if ((hook[i].symTblId == symTblId) && (!strcmp(hook[i].symbol->name, name)))
{
pHook = &(hook[i]);
if (index != NULL)
{
*index = i;
}
break;
}
}
return (pHook);
}
/*
** vxHook
** Hooks a symbol within a symbol table (if not already hooked).
*/
STATUS vxHook(SYMTAB_ID symTblId, /* symbol table to seachr for name */
char *name, /* name of symbol */
void *value, /* new value to replace symbol value with */
void **pValue) /* optional pointer receiving original value from symbol table */
{
STATUS result = ERROR;
SYMBOL *symbol;
VXHOOK *pHook;
if ((name != NULL) && (value != NULL))
{
pHook = vxHookGet(symTblId, name, NULL);
if (pHook == NULL) /* symbol not hooked, yet? */
{
if (hooks < MAX_HOOKS) /* free entries available? */
{
pHook = &(hook[hooks]);
symbol = symEach(symTblId, symbolIterator, (int)name);
if (symbol != NULL) /* symbol found? */
{
pHook->symTblId = symTblId;
pHook->symbol = symbol;
pHook->originalValue = symbol->value;
pHook->hookedValue = value;
if (pValue != NULL)
{
*pValue = symbol->value;
}
/* install hook */
symbol->value = value;
printf("Value of symbol '%s' modified from 0x%x to 0x%x.\n", name, pHook->originalValue, pHook->hookedValue);
hooks++;
result = OK;
}
else
{
printf("Symbol '%s' not found in symTblId=0x%08x.\n", name, symTblId);
}
}
else
{
printf("Maximum number of hooks (%d) reached.\n", MAX_HOOKS);
}
}
else
{
printf("Symbol '%s' in symTblId=0x%08x already hooked.\n", name, symTblId);
}
}
return (result);
}
/*
** vxHookList
** Prints a list of all installed hooks to stdout.
*/
STATUS vxHookList(void)
{
int i;
printf(" name symTblId value original\n");
printf("------------------- ---------- ---------- ----------\n");
for (i = 0; i < hooks; i++)
{
printf("%3d: 0x%08x %s\n", i, hook[i].symTblId, hook[i].symbol->name);
}
return (OK);
}
/*
** vxUnhook
** Unhooks a hooked symbol (restoring the original value).
*/
STATUS vxUnhook(SYMTAB_ID symTblId, /* symbol table to search for name */
char *name) /* name of symbol */
{
STATUS result = ERROR;
VXHOOK *pHook;
int i;
pHook = vxHookGet(symTblId, name, &i);
if (pHook != NULL)
{
pHook->symbol->value = pHook->originalValue;
printf("Original value 0x%x of symbol '%s' restored.\n", pHook->originalValue, name);
/* remove hook */
hooks--;
/* shift remaining hooks... */
for (; i < hooks; i++)
{
memcpy(&(hook[i]), &(hook[i + 1]), sizeof(VXHOOK));
}
result = OK;
}
else
{
printf("Hook for '%s' (symTblId=0x%08x) not found.\n", name, symTblId);
}
return (result);
}
To hook wvEvent(..) calls you have to do the following:
#include <wvLib.h>
#include <symLib.h>
STATUS (*WVEVENT_FPTR)(event_t, char *, size_t);
WVEVENT_FPTR orig_wvEvent = wvEvent;
STATUS my_wvEvent(event_t usrEventId, /* event */
char * buffer, /* buffer */
size_t bufSize) /* buffer size */
{
/* create a list of usrEventId... */
return (orig_wvEvent(usrEventId, buffer, bufSize));
}
STATUS hookWvEvents(void)
{
STATUS result = ERROR;
result = vxHook(sysSymTbl, "wvEvent", my_wvEvent, &orig_wvEvent);
return (result);
}
After calling hookWvEvents you can load your application and all calls to wvEvent from within your application will be redirected to my_wvEvent (and then passed on to the original wvEvent function). Remember that hooked symbols stay hooked for your application even if you unhook the symbol using vxUnhook.
Note: This mechanism is also very helpful for application testing and debugging since you can stress your application by forcing system calls to fail...

Creating a RAW UDP connection in lwip ARP

I am currently working to create a simple transfer protocol over Ethernet. I have a SP605 Xilinx evaluation board which I am using to debug the Ethernet portion of our project. I attempted to cannibalize the example but have so far been unsuccessful. Currently, the communication needs to only be one way. Currently, I am trying to see the data being sent with netcat. I also have wireshark open and am seeing the system get stuck repeatedly asking:
2217 1323.697811000 Xilinx_00:01:02 Broadcast
ARP 60 Who has 192.168.1.11? Tell 192.168.1.10
I can see the Host computer reply with:
2217 1323.697811000 Xilinx_00:01:02 Broadcast
ARP 60 Who has 192.168.1.11? Tell 192.168.1.10
I feel like I have some issues with the configuration but cannot figure out how what it is. I think it might have something to do with a not having a recv handler set but I am not sure.
Below is the code I am using. lwip_init() is mimicking the call from the examples provided by Xilinx.
/*
* main.c
*
* Created on: Sep 24, 2013
* Author: Ian
*/
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include "lwip/init.h"
#include "xparameters.h"
#include "netif/xadapter.h"
#include "xenv_standalone.h"
#include "platform_config.h"
#include "xparameters.h"
#include "xintc.h"
#include "xil_exception.h"
#include "mb_interface.h"
#include "xtmrctr_l.h"
#include "lwip/udp.h"
#include "lwipopts.h"
#include "xil_printf.h"
struct ip_addr ipaddr, ipaddr_remote, netmask, gw;
void udp_test(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
void print_ip(char *msg, struct ip_addr *ip)
{
print(msg);
xil_printf("%d.%d.%d.%d\r\n", ip4_addr1(ip), ip4_addr2(ip),
ip4_addr3(ip), ip4_addr4(ip));
}
void print_ip_settings(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw)
{
print_ip("Board IP: ", ip);
print_ip("Netmask : ", mask);
print_ip("Gateway : ", gw);
}
int main()
{
err_t error;
struct netif *netif, server_netif;
struct udp_pcb *udp_1;
struct pbuf *p;
char data[8] = "01234567";
u16_t Port;
Port = 69;
int count = 0;
int n = 0;
int buflen = 8;
/* the mac address of the board. this should be unique per board */
unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };
netif = &server_netif;
xil_printf("\r\n\r\n");
xil_printf("-----lwIP RAW Application ------\r\n");
/* initliaze IP addresses to be used */
IP4_ADDR(&ipaddr_remote, 192, 168, 1, 11);
IP4_ADDR(&ipaddr, 192, 168, 1, 10);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 192, 168, 1, 1);
print_ip_settings(&ipaddr, &netmask, &gw);
lwip_init();
if (!xemac_add(netif, &ipaddr, &netmask, &gw, mac_ethernet_address, PLATFORM_EMAC_BASEADDR)) {
xil_printf("Error adding N/W interface\r\n");
return -1;
}
netif_set_default(netif);
netif_set_up(netif);
Xil_ExceptionEnable(); //Setup complete start interrupts
udp_1 = udp_new();
error = udp_bind(udp_1, IP_ADDR_ANY, Port);
if (error != 0)
{
xil_printf("Failed %d\r\n", error);
}
else if (error == 0)
{
xil_printf("Success\r\n");
}
error = udp_connect(udp_1, &ipaddr_remote, Port);
if (error != 0)
{
xil_printf("Failed %d\r\n", error);
}
else if (error == 0)
{
xil_printf("Success\r\n");
}
while(1)
{
count++;
xemacif_input(netif);
if (count == 100000)
{
p = pbuf_alloc(PBUF_TRANSPORT, buflen, PBUF_POOL);
if (!p) {
xil_printf("error allocating pbuf\r\n");
return ERR_MEM;
}
memcpy(p->payload, data, buflen);
udp_send(udp_1, p);
xil_printf("SEND\r\n");
count = 0;
pbuf_free(p);
}
}
data[1] = '2';
}
Ok, so basically here is what I found.
The Xilinx xapp1026 had issues with the sp605_AxiEth_32kb_Cache project when I used it. It was hanging at the start interrupts. I was not able to diagnose the project BUT I switched to the sp605_EthernetLite_32kb_Cache example project. I can only assume that the failure of the MicroBlaze interrupts to initialize caused the ARP to fail to get added and forced the system into the loop repeatedly. It is still unclear why the interrupt failed to initialize in the AxiEth example.
Once here I was able to get a program to work by stripping down the provided system and using the following code:
/*
* Copyright (c) 2007 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#include <stdio.h>
#include <string.h>
#include "lwip/udp.h"
#include "xparameters.h"
#include "netif/xadapter.h"
#include "platform.h"
#include "platform_config.h"
#include "lwipopts.h"
#ifndef __PPC__
#include "xil_printf.h"
#endif
void print_headers();
int start_applications();
int transfer_data();
void platform_enable_interrupts();
void lwip_init(void);
void tcp_fasttmr(void);
void tcp_slowtmr(void);
#if LWIP_DHCP==1
extern volatile int dhcp_timoutcntr;
err_t dhcp_start(struct netif *netif);
#endif
extern volatile int TxPerfConnMonCntr;
extern volatile int TcpFastTmrFlag;
extern volatile int TcpSlowTmrFlag;
void print_ip(char *msg, struct ip_addr *ip)
{
print(msg);
xil_printf("%d.%d.%d.%d\r\n", ip4_addr1(ip), ip4_addr2(ip),
ip4_addr3(ip), ip4_addr4(ip));
}
void print_ip_settings(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw)
{
print_ip("Board IP: ", ip);
print_ip("Netmask : ", mask);
print_ip("Gateway : ", gw);
}
int main()
{
struct netif *netif, server_netif;
struct ip_addr ipaddr, netmask, gw;
// Added stuff for the creation of a basic UDP
err_t error;
struct ip_addr ip_remote;
struct udp_pcb *udp_1;
struct pbuf *p;
char data[8] = "01234567";
u16_t Port = 12;
int buflen = 8;
int count = 0;
/* the mac address of the board. this should be unique per board */
unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };
netif = &server_netif;
if (init_platform() < 0) {
xil_printf("ERROR initializing platform.\r\n");
return -1;
}
xil_printf("\r\n\r\n");
xil_printf("-----lwIP RAW Mode Demo Application ------\r\n");
/* initliaze IP addresses to be used */
#if (LWIP_DHCP==0)
IP4_ADDR(&ipaddr, 192, 168, 1, 10);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 192, 168, 1, 1);
print_ip_settings(&ipaddr, &netmask, &gw);
#endif
lwip_init();
#if (LWIP_DHCP==1)
ipaddr.addr = 0;
gw.addr = 0;
netmask.addr = 0;
#endif
/* Add network interface to the netif_list, and set it as default */
if (!xemac_add(netif, &ipaddr, &netmask, &gw, mac_ethernet_address, PLATFORM_EMAC_BASEADDR)) {
xil_printf("Error adding N/W interface\r\n");
return -1;
}
netif_set_default(netif);
/* specify that the network if is up */
netif_set_up(netif);
/* now enable interrupts */
platform_enable_interrupts();
#if (LWIP_DHCP==1)
/* Create a new DHCP client for this interface.
* Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
* the predefined regular intervals after starting the client.
*/
dhcp_start(netif);
dhcp_timoutcntr = 24;
TxPerfConnMonCntr = 0;
while(((netif->ip_addr.addr) == 0) && (dhcp_timoutcntr > 0)) {
xemacif_input(netif);
if (TcpFastTmrFlag) {
tcp_fasttmr();
TcpFastTmrFlag = 0;
}
if (TcpSlowTmrFlag) {
tcp_slowtmr();
TcpSlowTmrFlag = 0;
}
}
if (dhcp_timoutcntr <= 0) {
if ((netif->ip_addr.addr) == 0) {
xil_printf("DHCP Timeout\r\n");
xil_printf("Configuring default IP of 192.168.1.10\r\n");
IP4_ADDR(&(netif->ip_addr), 192, 168, 1, 10);
IP4_ADDR(&(netif->netmask), 255, 255, 255, 0);
IP4_ADDR(&(netif->gw), 192, 168, 1, 1);
}
}
/* receive and process packets */
print_ip_settings(&(netif->ip_addr), &(netif->netmask), &(netif->gw));
#endif
/* start the application (web server, rxtest, txtest, etc..) */
xil_printf("Setup Done");
IP4_ADDR(&ip_remote, 192, 168, 1, 11);
udp_1 = udp_new();
error = udp_bind(udp_1, IP_ADDR_ANY, Port);
if (error != 0)
{
xil_printf("Failed %d\r\n", error);
}
else if (error == 0)
{
xil_printf("Success\r\n");
}
error = udp_connect(udp_1, &ip_remote, Port);
if (error != 0)
{
xil_printf("Failed %d\r\n", error);
}
else if (error == 0)
{
xil_printf("Success\r\n");
}
while (1)
{
xemacif_input(netif);
count++;
if (count == 80000)
{
p = pbuf_alloc(PBUF_TRANSPORT, buflen, PBUF_POOL);
if (!p) {
xil_printf("error allocating pbuf\r\n");
return ERR_MEM;
}
memcpy(p->payload, data, buflen);
udp_send(udp_1, p);
xil_printf("SEND\r\n");
count = 0;
pbuf_free(p);
}
}
/* never reached */
cleanup_platform();
return 0;
}
----Edit ----
So you know how people figure it out then don't leave an answer. Well here was my problem with the orginal code (I think..) the line of code xemacif_input(netif); gives the Ethernet the ability to process the arp call without it the FPGA will sending out the ARP and then not receiving it will ask repeatedly.
The previous code does appear to have the correct line of code in it. So it might have been a mistake in how the interrupts were configured.
I got this example working and implemented it in my project. If you have questions about this please ask and I will try and give the best answers I can.

suspicious RCU usage?

I'm running custom Fedora 17 Kernel 3.3.0-0.rc5.git3.1.yfkm2.fc17.x86_64, and the warning was shown on dmesg:
[ 858.634304]
[ 858.634324] ===============================
[ 858.634350] [ INFO: suspicious RCU usage. ]
[ 858.634375] 3.3.0-0.rc5.git3.1.yfkm2.fc17.x86_64 #1 Not tainted
[ 858.634409] -------------------------------
[ 858.634435] kernel/pid.c:425 find_task_by_pid_ns() needs rcu_read_lock() protection!
[ 858.634478]
[ 858.634479] other info that might help us debug this:
[ 858.634480]
[ 858.634528]
[ 858.634529] rcu_scheduler_active = 1, debug_locks = 0
[ 858.634567] no locks held by monitor/10550.
[ 858.634591]
[ 858.634592] stack backtrace:
[ 858.634620] Pid: 10550, comm: monitor Not tainted 3.3.0-0.rc5.git3.1.yfkm2.fc17.x86_64 #1
[ 858.634666] Call Trace:
[ 858.634688] [<ffffffff810c8c55>] lockdep_rcu_suspicious+0xe5/0x100
[ 858.634727] [<ffffffff81086921>] find_task_by_pid_ns+0x81/0xa0
[ 858.634762] [<ffffffff81086962>] find_task_by_vpid+0x22/0x30
[ 858.634798] [<ffffffff8131ccd5>] yfkm2_is_pid_running+0x15/0x40
[ 858.634835] [<ffffffff8131ce54>] sys_yfkm2_monitor+0x14/0x80
[ 858.634870] [<ffffffff816a6ba9>] system_call_fastpath+0x16/0x1b
monitor is user application that call sys_yfkm2_monitor syscall passing a pid to it. The custom code worked as expected but I'm curious with the warning message shown on dmesg. What am I doing wrong?
The user application monitor.c:
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#define SYS_yfkm2_monitor __NR_yfkm2_monitor
#define SYS_yfkm2_notifyme __NR_yfkm2_notifyme
int main (int argc, char *argv[])
{
if (argc < 2) {
printf("Error. Use %s <PID>\n", argv[0]);
return 1;
}
pid_t pid = atoi(argv[1]);
long ret;
ret = syscall(SYS_yfkm2_monitor, pid);
if (ret == 0){
printf("Sucess on adding %d!\n", pid);
return 0;
} else {
printf("Failure! Is %s a valid PID?\n", argv[1]);
return 1;
}
}
The Kernel code:
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/kthread.h>
#define YFKM2_KT_TIMEOUT (1*HZ) /* 1 second */
struct yfkm2 {
pid_t monitor; /* PID to monitor */
pid_t notifyme; /* PID to notify */
struct list_head list; /* Linked List struct */
};
/* How many Kernel Threads are running? */
atomic_t yfkm2_kthread_run_count = ATOMIC_INIT(0);
/* Define and initialize yfkm2_(linked)list */
LIST_HEAD(yfkm2_list);
/* Define and initialize yfkm2_(read&write)lock */
DEFINE_RWLOCK(yfkm2_lock);
/*
* yfkm2_is_pid_running(pid_t pid)
*
* Check if pid is running
*
* return 0 if pid is running
* return 1 if pid is not running
*/
int yfkm2_is_pid_running(pid_t pid)
{
struct task_struct *q;
q = find_task_by_vpid(pid);
if (q != NULL && q->pid == pid)
return 0;
return 1;
}
/*
* yfkm2_kill(pid_t pid)
*
* Kills pid
*
* return 0 if pid was running and send SIGKILL to pid
* return 1 if pid is not running
*/
int yfkm2_kill(pid_t pid)
{
struct task_struct *q;
q = find_task_by_vpid(pid);
if (q != NULL) {
force_sig(SIGKILL, q);
return 0;
}
return 1;
}
/*
* int yfkm2_kthread(void *data)
*
* The Kernel Thread
*
* Traverse the yfkm2_list looking for yfkm2->notifyme that are not 0.
* If any found, check if correspondent yfkm2->monitor is still running. If not
* kill yfkm2->notifyme. After traversing the list, check if the list is empty.
* If so return 0. If not sleep one second and start again.
*
* return 0 if yfkm2_list is empty
* should never return 1
*/
int yfkm2_kthread(void *data) /* data is NEVER used */
{
struct yfkm2 *yfkm2_tmp, *yfkm2_tmp2;
bool empty;
while (true) {
/* Needs write protection due possible item removal from list */
write_lock(&yfkm2_lock); /* Write lock */
list_for_each_entry_safe(yfkm2_tmp, yfkm2_tmp2,
&yfkm2_list, list) {
if (yfkm2_tmp->notifyme != 0) {
if (yfkm2_is_pid_running(yfkm2_tmp->monitor) != 0) {
yfkm2_kill(yfkm2_tmp->notifyme);
list_del(&yfkm2_tmp->list);
kfree(yfkm2_tmp);
}
}
}
write_unlock(&yfkm2_lock); /* Write unlock */
read_lock(&yfkm2_lock); /* Read lock */
empty = list_empty(&yfkm2_list);
read_unlock(&yfkm2_lock); /* Read unlock */
if (empty) {
/* The counter is increased at sys_yfkm2_notifyme()
* Before exit, decrease atomic run counter */
atomic_dec(&yfkm2_kthread_run_count);
return 0;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(YFKM2_KT_TIMEOUT);
}
/* Before exit, decrease atomic run counter */
atomic_dec(&yfkm2_kthread_run_count);
return 1;
}
/*
* asmlinkage long sys_yfkm2_monitor(pid_t monitor)
*
* The system call that check if monitor correspond to a running pid and stores
* monitor at yfkm2_list->monitor
*
* return 0 if pid is running
* return 1 if pid is not running
*/
asmlinkage long sys_yfkm2_monitor(pid_t monitor)
{
struct yfkm2 *yfkm2_tmp;
if (yfkm2_is_pid_running(monitor) == 0) {
yfkm2_tmp = kmalloc(sizeof(*yfkm2_tmp), GFP_KERNEL);
yfkm2_tmp->monitor = monitor;
yfkm2_tmp->notifyme = 0;
write_lock(&yfkm2_lock);
list_add(&yfkm2_tmp->list, &yfkm2_list);
write_unlock(&yfkm2_lock);
return 0;
}
return 1;
}
/*
* asmlinkage long sys_yfkm2_notifyme(pid_t monitor, pid_t notifyme)
*
* The system call that looks for monitor at yfkm2_list->monitor. If found
* store notifyme at yfkm2_list->notifyme. It also starts the kernel thread
* if it is not running.
*
* return 0 if pid is running
* return 1 if pid is not running
*/
asmlinkage long sys_yfkm2_notifyme(pid_t monitor, pid_t notifyme)
{
struct yfkm2 *yfkm2_tmp;
bool found_monitored_pid = false;
write_lock(&yfkm2_lock); /* Write lock */
list_for_each_entry(yfkm2_tmp, &yfkm2_list, list) {
if (yfkm2_tmp->monitor == monitor) {
yfkm2_tmp->notifyme = notifyme;
found_monitored_pid = true;
break;
}
}
write_unlock(&yfkm2_lock); /* Write unlock */
if (found_monitored_pid) {
if (atomic_read(&yfkm2_kthread_run_count) < 1) {
/* The counter is decreased at yfkm2_kthread()
* Before start, increase atomic run counter */
atomic_inc(&yfkm2_kthread_run_count);
kthread_run(&yfkm2_kthread, NULL, "yfkm2_kthread");
}
return 0;
} else {
return 1;
}
}
You are not performing correct locking on the task list. For example, your yfkm2_kill() function should be:
int yfkm2_kill(pid_t pid)
{
struct task_struct *q;
rcu_read_lock();
q = find_task_by_vpid(pid);
if (q)
get_task_struct(q);
rcu_read_unlock();
if (q == NULL)
return 1;
force_sig(SIGKILL, q);
put_task_struct(q);
return 0;
}
...but your whole design appears to be severely racy. For example, one of the ->monitor tasks could exit and be replaced with a new, different task with the same PID before your kernel thread notices.
You seem to be running code without the required locks.
Such things tend to work, except that they crash once in a while (possibly a long while).
I don't know these functions so much, but it seems like find_task_by_vpid should be called under some RCU lock (probably the one that protects the process list), in read mode.