Error: identifier "LCD_E_PORT" is undefined - c

Why I get the error: identifier "LCD_E_PORT" is undefined in this code:
#include <msp430f5438a.h>
#include "IO_functions.h"
#define LCD_E_PORT PORT_6
#define LCD_E PIN_4
#include "LCD1602.h"
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P4DIR = 0x03;
P4OUT = 0x00;
output_bit(PORT_4, PIN_7, 1);
output_bit(PORT_4, PIN_7, 0);
lcd_send_nibble(0x0f);
while(1)
{
P4OUT ^= BIT0;
__delay_cycles(500000);
}
}
Since I have defined LCD_E_PORT at the top of my code I don't understand where this error comes from.
This is LCD1602.c in which I am using LCD_E_PORT:
#include <msp430f5438a.h>
#include "LCD1602.h"
#include "IO_functions.h"
void lcd_send_nibble(unsigned char nibble)
{
output_bit(LCD_DB4_PORT, LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5_PORT, LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6_PORT, LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7_PORT, LCD_DB7, !!(nibble & 8));
__delay_cycles(8);
output_bit(LCD_E_PORT, LCD_E, 1);
__delay_cycles(16);
output_bit(LCD_E_PORT, LCD_E, 0);
}
void lcd_send_byte(unsigned char data_instr, unsigned char data)
{
output_bit(LCD_RS_PORT, LCD_RS, 0);
__delay_cycles(480);
if(data_instr == DATA)
output_bit(LCD_RS_PORT, LCD_RS, 1);
else
output_bit(LCD_RS_PORT, LCD_RS, 0);
__delay_cycles(8);
output_bit(LCD_E_PORT, LCD_E, 0);
lcd_send_nibble(data >> 4);
lcd_send_nibble(data & 0x0F);
}
void lcd_init(void)
{
unsigned char i;
output_bit(LCD_RS_PORT, LCD_RS, 0);
output_bit(LCD_E_PORT, LCD_E, 0);
__delay_cycles(120000);
for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
__delay_cycles(25000);
}
lcd_send_nibble(0x02);
lcd_send_byte(INSTR, 0x28);
__delay_cycles(25000);
lcd_send_byte(INSTR, 0x0C);
__delay_cycles(25000);
lcd_send_byte(INSTR, 0x01);
__delay_cycles(25000);
lcd_send_byte(INSTR, 0x06);
__delay_cycles(25000);
}

As per the updated code, the definition of LCD_E_PORT is not visible from LCD1602.c file.
You might want to add the #define in the header file (LCD1602.h or any other, at your choice) itself which will be included in all the source files making use of the macro.

Related

Segmentation Failure with print and write instructions, in Implementation between Fortran and C

I'm trying to call a C function from Fortran, using the iso_c_binding interoperability. However, I am getting a SegFault error when trying to use print and write statements. Without the print and write statements the code works fine, but I need these statements to create an output file with the simulation data. Does anyone know how to solve this problem?
Note: I am using Ubuntu 20.04, GFortran, and GCC to compile the respective source codes.
gcc -c subroutine_in_c.c
gfortran -o exec main.f90 subroutine_in_c.o -lwiringPi
main.f90:
PROGRAM main
USE, INTRINSIC:: iso_c_binding, ONLY: C_FLOAT
IMPLICIT NONE
REAL(KIND = 4) :: leitura_sensor = 0.0
INTERFACE
SUBROUTINE ler_sensores(s1) BIND(C)
USE, INTRINSIC :: iso_c_binding, ONLY: C_FLOAT
IMPLICIT NONE
REAL(KIND=C_FLOAT) :: s1
END SUBROUTINE ler_sensores
END INTERFACE
!print*, 'Call subroutine in C language'
call ler_sensores(leitura_sensor)
!print*, 'Return to main.f90'
OPEN(UNIT=1, FILE='output.txt', STATUS='unknown')
WRITE(1,*) leitura_sensor
CLOSE(UNIT=1)
END PROGRAM main
subroutine_in_c.c:
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <wiringPiSPI.h>
#include <wiringPiI2C.h>
#define LCDADDR 0x27 //IIC LCD address
#define BLEN 1 //1--open backlight,0--close backlight
#define CHAN_CONFIG_SINGLE 8 //setup channel 0 as Single-ended input
#define SPICHANNEL 0 //MCP3008 connect to SPI0
#define ANALOGCHANNEL 0 //Potentiometer connect MCP3008 analog channel 0
#define ANALOGCHANNEL2 1
static int spifd;
static int i2cfd;
void
spiSetup (int spiChannel)
{
if ((spifd = wiringPiSPISetup (spiChannel, 10000)) < 0)
{
fprintf (stderr, "Can't open the SPI bus: %s\n", strerror (errno)) ;
exit (EXIT_FAILURE) ;
}
}
int
myAnalogRead(int spiChannel,int channelConfig,int analogChannel)
{
if (analogChannel<0 || analogChannel>7)
return -1;
unsigned char buffer[3] = {1}; // start bit
buffer[1] = (channelConfig+analogChannel) << 4;
wiringPiSPIDataRW(spiChannel, buffer, 3);
return ( (buffer[1] & 3 ) << 8 ) + buffer[2]; // get last 10 bits
}
//write a word to lcd
void
write_word(int data)
{
int temp = data;
if ( BLEN == 1 )
temp |= 0x08;
else
temp &= 0xF7;
wiringPiI2CWrite(i2cfd, temp);
}
//send command to lcd
void
send_command(int comm)
{
int buf;
// Send bit7-4 firstly
buf = comm & 0xF0;
buf |= 0x04; // RS = 0, RW = 0, EN = 1
write_word(buf);
delay(2);
buf &= 0xFB; // Make EN = 0
write_word(buf);
// Send bit3-0 secondly
buf = (comm & 0x0F) << 4;
buf |= 0x04; // RS = 0, RW = 0, EN = 1
write_word(buf);
delay(2);
buf &= 0xFB; // Make EN = 0
write_word(buf);
}
//send data to lcd
void
send_data(int data)
{
int buf;
// Send bit7-4 firstly
buf = data & 0xF0;
buf |= 0x05; // RS = 1, RW = 0, EN = 1
write_word(buf);
delay(2);
buf &= 0xFB; // Make EN = 0
write_word(buf);
// Send bit3-0 secondly
buf = (data & 0x0F) << 4;
buf |= 0x05; // RS = 1, RW = 0, EN = 1
write_word(buf);
delay(2);
buf &= 0xFB; // Make EN = 0
write_word(buf);
}
//initialize the lcd
void
init()
{
send_command(0x33); // Must initialize to 8-line mode at first
delay(5);
send_command(0x32); // Then initialize to 4-line mode
delay(5);
send_command(0x28); // 2 Lines & 5*7 dots
delay(5);
send_command(0x0C); // Enable display without cursor
delay(5);
send_command(0x01); // Clear Screen
wiringPiI2CWrite(i2cfd, 0x08);
}
//clear screen
void
clear()
{
send_command(0x01); //clear Screen
}
//Print the message on the lcd
void
write(int x, int y, char data[])
{
int addr, i;
int tmp;
if (x < 0) x = 0;
if (x > 15) x = 15;
if (y < 0) y = 0;
if (y > 1) y = 1;
// Move cursor
addr = 0x80 + 0x40 * y + x;
send_command(addr);
tmp = strlen(data);
for (i = 0; i < tmp; i++) {
send_data(data[i]);
}
}
void
ler_sensores(float *s1)
{
int adc;
int adc2;
int i;
float voltage;
float voltage2;
char buf[5];
if (wiringPiSetup() < 0)
{
fprintf(stderr,"Can't init wiringPi: %s\n",strerror(errno));
exit(EXIT_FAILURE);
}
spiSetup(SPICHANNEL);//init spi
i2cfd = wiringPiI2CSetup(LCDADDR); //init i2c
init(); //init LCD
clear(); //clear screen
for (i = 0; i <25; i++) {
adc = myAnalogRead(SPICHANNEL,CHAN_CONFIG_SINGLE,ANALOGCHANNEL);
adc2 = myAnalogRead(SPICHANNEL, CHAN_CONFIG_SINGLE, ANALOGCHANNEL2);
voltage = adc/1024.*20.0;
write(0,0,"Ch Linear:");
sprintf(buf,"%2.2f",voltage);//float change to string
write(10,0,buf);//print voltage on lcd
write(15,0,"V");//print unit
write(0,1,"Ch Logarit:");
voltage2 = adc2/1024.*20.0;
sprintf(buf,"%2.2f",voltage2);
write(11,1, buf);
write(16,1,"V");
delay(1000);
}
*s1 = voltage;
}
Thank you in advance to everyone who helps.
This question probably deserves an answer even if the reason for the problem is the obscure one, identified by Craig Estay.
Gfortran's runtime library, called when using the print and write statements, contains calls to write() and having another C function called write will cause the gfortran runtime to call a wrong function.
It can easily be tested in a simple program like this:
testwrite.c:
#include "stdio.h"
void write(){
puts("my C write");
}
testwrite.f90:
print *,"test print"
write(*,*) "test write"
end
When using gfortran testwrite.c testwrite.f90, the output is:
my C write
my C write
my C write
my C write
The same output appears when using icc testwrite.c -c -o c.o and ifort c.o testwrite.f90.

How to turn on a LED with specific address on dot-matrix 74HC595?

I have problem when want to determine the address for each LED in dot-matrix 8x8 74HC595, im trying to light on only 1 LED specifically with the address. i have tried many tutorial and documentation but still no luck to light on only 1 LED with spesific location.
this is my circuit design :
https://www.sunfounder.com/learn/Super_Kit_V2_for_RaspberryPi/lesson-12-driving-dot-matrix-by-74hc595-super-kit-for-raspberrypi.html
my code with C:
#include <wiringPi.h>
#include <stdio.h>
#define SDI 0 //serial data input
#define RCLK 1 //memory clock input
#define SRCLK 2 //shift register clock input
unsigned char LED[8] ={0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
void pulse(int pin)
{
digitalWrite(pin, 0);
digitalWrite(pin, 1);
}
void ShiftOUT(unsigned char byte)
{
int i;
for(i=0;i<8;i++)
{
// char a = byte & (0x80 >> i)) > 0;
digitalWrite(SDI, (( byte & (0x80 >> i)) > 0));
printf("%d", (( byte >> i > 0)));
pulse(SRCLK);
}
printf("\n","==================");
}
void init(void)
{
pinMode(SDI, OUTPUT);
pinMode(RCLK, OUTPUT);
pinMode(SRCLK, OUTPUT);
digitalWrite(SDI, 0);
digitalWrite(RCLK, 0);
digitalWrite(SRCLK, 0);
}
int main(void)
{
int i;
if(wiringPiSetup() == -1)
{
printf("setup wiringPi failed !");
return 1;
}
init();
while(1)
{
for(i=0;i<8;i++)
{
ShiftOUT(LED[i]);
pulse(RCLK);
// printf("=======pull latch========");
// printf("\n");
delay(150);
}
delay(500);
}
return 0;
}
This code i tried will light on 1 row,i want to light on 1 LED with spesific location
Here is the link i use for simulation to addressing the LED : https://www.riyas.org/2013/12/online-led-matrix-font-generator-with.html
Any help?Thank you

Bash ping script with LCD error message errors

I am working in Debian and I am trying to write a script that will ping a host (192.168.10.30) every 10 seconds.
Whenever the ping is not successful, I want to have the message "VPN Lost" be displayed on my LCD screen. Once the ping is successful again the "VPN Lost" message will disappear from my LCD screen, and the screen will display "STS300".
The code below keeps giving me an error when I try to compile it, and I do not understand why. (The code compiles fine, but once I added in the code for the ping it won't compile). The code that is giving me trouble is between the lines lcd_command(LINE_3); and lcd_command(LINE_4);
I am fairly new to this...
The errors I am getting are...
lcdSignal.c: In function 'main': lcdSignal.c:190:10: error: expected
'(' before 'true'
lcdSignal.c:190:10: error: 'true' undeclared (first use in this
function)
lcdSignal.c:190:10: note: each undeclared identifier is reported only
once for each function it appears in
lcdSignal.c:191:3: error: 'ping' undeclared (first use in this
function)
lcdSignal.c:191:12: error: too many decimal points in number
lcdSignal.c:191:9: error: 'c1' undeclared (first use in this function)
lcdSignal.c:191:12: error: expected ';' before numeric constant
lcdSignal.c:192:3: error: expected 'while' before 'lcd_writechars'
lcdSignal.c:193:7: error: expected '(' before '[' token
lcdSignal.c:193:12: error: '$' undeclared (first use in this function)
lcdSignal.c:193:19: error: unknown type name 'then'
lcdSignal.c:194:18: error: expected declaration specifiers or '...'
before string constant
lcdSignal.c:195:3: error: 'fi' undeclared (first use in this function)
lcdSignal.c:196:9: error: expected ';' before numeric constant
If someone could help me, I would greatly appreciate it!!!
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include "evgpio.h"
#include "STSConfig.h" // This file is where the strings are modified
void lcd_init(void);
void lcd_wait(void);
void lcd_command(uint16_t);
void lcd_writechars(unsigned char *dat);
// These are microsecond delays
#define SETUP 1
#define PULSE 2
#define HOLD 1
#define LINE_1 0x80 // beginning position of LCD line 1
#define LINE_2 0xC0 // beginning position of LCD line 2
#define LINE_3 0x94 // beginning position of LCD line 3
#define LINE_4 0xD4 // beginning position of LCD line 4
#define LCD_D0 74
#define LCD_D1 75
#define LCD_D2 72
#define LCD_D3 73
#define LCD_D4 70
#define LCD_D5 71
#define LCD_D6 68
#define LCD_D7 69
#define LCD_EN 64
#define LCD_WR 65
#define LCD_RS 66
#define LCD_BIAS 67
void lcd_write(uint8_t out)
{
evsetdata(LCD_D0, out & (1 << 0));
evsetdata(LCD_D1, out & (1 << 1));
evsetdata(LCD_D2, out & (1 << 2));
evsetdata(LCD_D3, out & (1 << 3));
evsetdata(LCD_D4, out & (1 << 4));
evsetdata(LCD_D5, out & (1 << 5));
evsetdata(LCD_D6, out & (1 << 6));
evsetdata(LCD_D7, out & (1 << 7));
}
void lcd_ddr(uint8_t out)
{
evsetddr(LCD_D0, out & (1 << 0));
evsetddr(LCD_D1, out & (1 << 1));
evsetddr(LCD_D2, out & (1 << 2));
evsetddr(LCD_D3, out & (1 << 3));
evsetddr(LCD_D4, out & (1 << 4));
evsetddr(LCD_D5, out & (1 << 5));
evsetddr(LCD_D6, out & (1 << 6));
evsetddr(LCD_D7, out & (1 << 7));
}
uint8_t lcd_read()
{
uint8_t out = 0;
out |= (evgetin(LCD_D0) << 0);
out |= (evgetin(LCD_D1) << 1);
out |= (evgetin(LCD_D2) << 2);
out |= (evgetin(LCD_D3) << 3);
out |= (evgetin(LCD_D4) << 4);
out |= (evgetin(LCD_D5) << 5);
out |= (evgetin(LCD_D6) << 6);
out |= (evgetin(LCD_D7) << 7);
return out;
}
void lcd_enpulse()
{
usleep(SETUP);
evsetdata(LCD_EN, 1);
usleep(PULSE);
evsetdata(LCD_EN, 0);
usleep(HOLD);
}
void lcd_init(void)
{
evgpioinit();
// Data lines to inputs, control lines to outputs
lcd_ddr(0x0);
evsetddr(LCD_EN, 1);
evsetddr(LCD_RS, 1);
evsetddr(LCD_WR, 1);
// Set LCD_EN and LCD_RS low
evsetdata(LCD_EN, 0);
evsetdata(LCD_RS, 0);
// Set LCD_WR high
evsetdata(LCD_WR, 1);
usleep(15000);
lcd_command(0x38); // two rows, 5x7, 8 bit
usleep(4100);
lcd_command(0x38); // two rows, 5x7, 8 bit
usleep(100);
lcd_command(0x38); // two rows, 5x7, 8 bit
lcd_command(0x6); // cursor increment mode
lcd_wait();
//lcd_command(0x1); // clear display
// lcd_wait();
// lcd_command(0xc); // display on, blink off, cursor off
// lcd_wait();
lcd_command(0x2); // return home
evsetddr(LCD_BIAS, 1);
evsetdata(LCD_BIAS, 0);
}
void lcd_wait(void)
{
uint8_t in;
int i, dat, tries = 0;
lcd_ddr(0x0);
do {
// step 1, apply only RS & WR
evsetdata(LCD_RS, 0);
evsetdata(LCD_WR, 1); // low for write
lcd_enpulse();
usleep(1);
} while (in & 0x80 && tries++ < 5);
}
void lcd_command(uint16_t cmd)
{
lcd_ddr(0xff);
lcd_write(cmd);
evsetdata(LCD_WR, 0);
evsetdata(LCD_RS, 0);
lcd_enpulse();
}
void lcd_writechars(unsigned char *dat)
{
int i;
do {
lcd_wait();
lcd_ddr(0xff);
evsetdata(LCD_RS, 1);
evsetdata(LCD_WR, 0); // active low
lcd_write(*dat++);
lcd_enpulse();
} while (*dat);
}
int main(int argc, char *argv[])
{
char *temp = argv[1];
float sigStn = atof(temp);
float numBuf = (((sigStn-(-120))/(-70-(-120)))*100);
char buf[48];
if (numBuf >=9 && numBuf<=99) {
snprintf(buf, sizeof(buf), " Signal= %0.0f",numBuf);
strcat(buf,"% ");
} else {
snprintf(buf, sizeof(buf), " Signal= %0.0f",numBuf);
strcat(buf,"% ");
}
lcd_init();
lcd_command(LINE_1);
lcd_writechars(STS);
lcd_command(LINE_2);
if (numBuf > 100)
lcd_writechars(" Signal= 100% ");
else if(numBuf<0){
lcd_writechars(" Reconnecting ");
// lcd_writechars(" Signal = 0% ");
} else
lcd_writechars(buf);
lcd_command(LINE_3);
{while true; do
ping -c1 192.168.10.30 2>&1 /dev/null; //VPN IP
lcd_writechars("STS300");}
{if [[ ! $? ]]; then
lcd_writechars("VPN Lost");
fi;
sleep 10;
}
lcd_command(LINE_4);
lcd_writechars(BBPN);
return;
while (!feof(stdin)) {
unsigned char buf[512];
int i = 0;
lcd_wait();
if (i) {
// XXX: this seek addr may be different for different
// LCD sizes! -JO
lcd_command(0xa8); // set DDRAM addr to second row
} else
lcd_command(0x2); // return home
i = i ^ 0x1;
if (fgets(buf, sizeof(buf), stdin) != NULL) {
unsigned int len;
buf[0x27] = 0;
len = strlen(buf);
if (buf[len - 1] == '\n') buf[len - 1] = 0;
lcd_writechars(buf);
}
}
return 0;
}
The following lines of code in your program aren't C at all. They look like a fragment of shell script:
lcd_command(LINE_3);
{while true; do
ping -c1 192.168.10.30 2>&1 /dev/null; //VPN IP
lcd_writechars("STS300");}
{if [[ ! $? ]]; then
lcd_writechars("VPN Lost");
fi;
sleep 10;
}
This won't work. Rewrite this code in C. (The system() function may be helpful.)

uPP Device Driver is dropping data from buffer

I have written code for a uPP device driver to be used with an OMAPL138 based custom board for data acquisition through a camera lens. The code for my device driver is:
/*
* A device driver for the Texas Instruments
* Universal Paralllel Port (UPP)
*
* Modified by: Ali Shehryar <github.com/sshehryar>
*
*/
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/fs.h>
#include <linux/delay.h> //for "mdelay(...)"
#include <linux/interrupt.h>
#include <linux/cdev.h>
#include <linux/moduleparam.h>
#include <mach/da8xx.h>
#include <asm/sizes.h>
#include <asm/io.h>
#include <mach/mux.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
//SPRUH77A.PDF, Table 12-1. The Interrupt number assigned to the UPP module.
#define UPP_INTERRUPT 91
//SPRS586D.PDF, Table 2-4
#define DA850_UPP_BASE 0x01E16000
//SPRS586D.PDF, Table 5-117. Offsets from DA850_UPP_BASE
#define UPPCR 0x00000004
#define UPDLB 0x00000008
#define UPCTL 0x00000010
#define UPICR 0x00000014
#define UPIVR 0x00000018
#define UPTCR 0x0000001C
#define UPIER 0x00000024
#define UPIES 0x00000028
#define UPIEC 0x0000002C
#define UPEOI 0x00000030
#define UPID0 0x00000040
#define UPID1 0x00000044
#define UPID2 0x00000048
#define UPIS0 0x00000050
#define UPIS1 0x00000054
#define UPIS2 0x00000058
//SPRS586D.PDF, Table 2-4
#define DA850_PSC1_BASE 0x01E27000
//SPRUH77A.PDF, Table 9-7.
//"Power and Sleep Controller 1" (PSC1) Revision ID Register.
#define PSC_REVID 0x00000000
//SPRUH77A.PDF, Table 9-7.
//"Power Domain Transition Status" Register.
#define PSC_PTSTAT 0x00000128
//SPRUH77A.PDF, Table 9-2, Table 9-7.
//NOTE that in Table 9-2, UPP module has an LPSC number of 19...
#define PSC1_MDCTL_19 0x00000A4C //0xA00 + (19*4).
//SPRUH77A.PDF, Table 9-7.
//"Power Domain Transition Command Register" Register.
#define PSC_PTCMD 0x00000120
//DMA Status Register bitmasks used in the ISR handler....
#define EOLI 16
#define EOWI 8
#define ERRI 4
#define UORI 2
#define DPEI 1
#define UPIES_MASK 0x0000001F
///#define UPIES_MASK 0x1717 ---> Reverted back to 1717 because Window interrupt is not used, for now its useless
//To Enable all interrupts ---> #define UPIES_MASK 0x1F1F
/// Shehryar: These Parameters are to be modified and tweaked according to reqirements in realtime.
//The DMA PARAMETERS
#define UPP_BUF_SIZE 8192 //Need to lookup for an exact val (changed from 8192 on 2 DEc 14)
#define UPP_RX_LINE_COUNT 8 //Changed from 8
#define UPP_RX_LINE_SIZE 1024
#define UPP_RX_LINE_OFFSET 1024 //value changed from 1024 to 0 on 2 DEC 2014
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//MODIFIED BY: SHEHRYAR ---> Pg 888 General-Purpose Input/Output (GPIO) SPRUH82A–December 2011. Added 25-Nov-2014
#define DA850_GPIO_BASE 0x01E26000
//------------------------------------- 9/12/2014-----------------
//#define MY_BUFFER_SIZE 1048756
//----------------------------------------------------------------
//MODIFIED BY: SHEHRYAR. Offsets from GPIO_Base (SPRS653C.PDF TABLE 5-134)
#define DIR67 0x00000088
#define OUT_DATA67 0x0000008C
#define SET_DATA67 0x00000090
#define CLR_DATA67 0x00000094
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void *rxBuf;
static void __iomem *pinmux_base = 0;
static void __iomem *upp_base = 0;
static void __iomem *psc1_base = 0;
static void __iomem *gpio_base = 0;
static DECLARE_WAIT_QUEUE_HEAD(read_queue);
static int32_t read_pending = 0; // changed from static int
//set to '1' when loading this module to use the Digital Loopback (DLB)
//features,e.g:"insmod UPP_driver.ko loopbackMode=1"
static int loopbackMode = 0;
module_param( loopbackMode, int, S_IRUGO);
int EOWI_Count = 0; int UORI_count =0;
///////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////INTERRUPT SERVICE ROUTINE//////////////////////////////////////
//////////////////////////////////////SPRUH82A–December 2014 PAGE 1515////////////////////////////////
//SPRUGJ5B.PDF, Section 2.6.4
static irqreturn_t upp_ISR_handler(int irq, void *dev_id)
{
uint32_t regVal, status;
if (pinmux_base == 0)
{
return IRQ_HANDLED;
}
status = ioread32( upp_base + UPIER );
while (status & 0x0000001F ) //0x1F1F is an interrupt bit-mask
{
//
//DMA Channel I (Channel A), Receiving data (We Need A (DMA Ch I ) to Rx Data instead of Tx ; 27th Nov 2014 - 10:38am)
//
if (status & EOLI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(EOLI, upp_base + UPIER );
//printk(KERN_INFO "DMA: EOLI\n");
//printk(KERN_INFO "DMA:EOLI. UPP_RX_LINE_SIZE[%d] UPP_RX_LINE_OFFSET[%d] UPP_RX_LINE_COUNT[%d] \n", UPP_RX_LINE_SIZE,UPP_RX_LINE_OFFSET,UPP_RX_LINE_COUNT );
//dump_Channel_regs();
}
if (status & EOWI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
//printk(KERN_INFO "DMA: EOWI\n");
iowrite32(EOWI, upp_base + UPIER );
read_pending = 8192;
wake_up_interruptible(&read_queue);
//add 1 to EOWI counter
EOWI_Count += 1;
// dump_Channel_regs();
}
if (status & ERRI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(ERRI, upp_base + UPIER );
//dump_Channel_regs();
}
if (status & UORI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(UORI, upp_base + UPIER );
UORI_count +=1;
//dump_Channel_regs();
}
if (status & DPEI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(DPEI, upp_base + UPIER );
//dump_Channel_regs();
}
//read again, and process if necessary.
status = ioread32( upp_base + UPIER );
}
//Clear UPEOI to allow future calls to this function.
regVal = ioread32( upp_base + UPEOI);
regVal &= 0xFFFFFF00;
regVal = 0;// End of Interrupt
iowrite32(regVal, upp_base + UPEOI);
return IRQ_HANDLED;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void pin_mux_set( int index, unsigned int bits )
{
static DEFINE_SPINLOCK(mux_spin_lock);
unsigned long flags;
unsigned int offset;
if ((index < 0) || (index > 19))
{
printk(KERN_INFO "pin_mux_set:index is out of range.\n");
return;
}
if (!pinmux_base)
{
//SRPUH77A.PDF,Table 11-3
if ((pinmux_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K)) == 0)
{
printk(KERN_INFO "pin_mux_set:Cannot fetch pinmux_base.\n");
return;
}
}
offset = 0x120 + (index * 4);
spin_lock_irqsave(&mux_spin_lock, flags);
iowrite32(bits, pinmux_base + offset);
spin_unlock_irqrestore(&mux_spin_lock, flags);
//NOTE: do NOT "iounmap" the pinmux_base pointer, as it is used
// in the ISR_handler.....
}
static void upp_pin_mux_init(void)
{
pin_mux_set( 13, 0x44440000 );
pin_mux_set( 14, 0x44444480 );
pin_mux_set( 15, 0x44444444 );
pin_mux_set( 16, 0x44444444 );
pin_mux_set( 17, 0x44444444 );
pin_mux_set( 18, 0x00444444 );
pin_mux_set( 19, 0x08888800 );
//pin_mux_print() ;
}
//SPRUGJ5B.PDF, Section 2.6.1.2.
static void upp_power_and_clocks( void )
{
/*
* Refer to:
* * Power and Sleep Controller (PSC), Chapter 9 in the TRM(SPRUH77A.PDF)
* * Device Clocking, Chapter 7 (esp Section 7.3.5) in the TRM.
*
*
*/
int regVal;
if (!psc1_base)
{
if ((psc1_base = ioremap(DA850_PSC1_BASE, SZ_4K)) == 0)
{
printk(KERN_INFO "upp_power_and_clocks:Cannot fetch psc1_base.\n");
return;
}
}
regVal = ioread32(psc1_base + PSC_REVID);
//PSC Revision ID should be "44825A00" per SPRUH77A.PDF, section 9.6.1
if (regVal == 0x44825A00)
{
printk( KERN_INFO "PSC_REVID = 0x%08X....OK\n", regVal);
}
else
{
printk( KERN_INFO "********ERROR: PSC_REVID = 0x%08X********\n", regVal);
}
// SPRUH77A.PDF, 9.3.2.1, Table 9-6, 9.6.10
// wait for GOSTAT[0] in PSTAT to clear to 0 ("No transition in progress")
while ( ioread32(psc1_base + PSC_PTSTAT) & 0x00000001 )
;
//
//SPRUH77A.PDF, 9.3.2.2, 9.6.19.
//Set NEXT bit in MDCTL19 to Enable(3h).
regVal = ioread32( psc1_base + PSC1_MDCTL_19 );
regVal |= 0x00000003;
iowrite32(regVal, psc1_base + PSC1_MDCTL_19);
//
//SPRUH77A.PDF, 9.3.2.3, 9.6.9.
//Set the GO[0] bit in PTCMD to 1 to initiate power-domain transition
regVal = ioread32(psc1_base + PSC_PTCMD);
regVal |= 0x00000001;
iowrite32(regVal, psc1_base + PSC_PTCMD);
//
// SPRUH77A.PDF, 9.3.2.4
// Wait for GOSTAT[0] in PTSTAT to clear to 0
while ( ioread32(psc1_base + PSC_PTSTAT) & 0x00000001 )
;
iounmap( psc1_base );
psc1_base = 0;
}
//SPRUGJ5B.PDF, Section 2.6.1.3, 2.6.1.4
static void upp_swrst( void )
{
int32_t reg_val;
if (!upp_base)
{
if ((upp_base = ioremap(DA850_UPP_BASE, SZ_4K)) == 0)
{
printk(KERN_INFO "upp_swrst:Cannot fetch upp_base.\n");
return;
}
}
//Fetch the UPP ID for the sake of sanity....Should be "44231100"
reg_val = ioread32( upp_base + 0 );
if (reg_val == 0x44231100 )
{
printk(KERN_INFO "UPP_UPPID = 0x%08X....OK\n", reg_val);
}
else
{
printk( KERN_INFO "********ERROR: UPP_UPPID = 0x%08X********\n", reg_val);
}
// SPRUH77A.PDF, Section 33.2.7.1.1, Table 33-12.
// clear EN bit of UPPCR to (temporarily) disable the UPP.
reg_val = ioread32( upp_base + UPPCR );
reg_val &= ~(1 << 3); //0xfffffff7;
iowrite32( reg_val, upp_base + UPPCR );
// SPRUH77A.PDF, Section 33.2.7.1.2, Table 33-12.
//poll "DMA Burst" (DB) bit of UPPCR to ensure DMA controller is idle
while ( ioread32( upp_base + UPPCR ) & (1 << 7) )
;
// SPRUH77A.PDF, Section 33.2.7.1.3, Table 33-12.
// assert SWRST bit (bit 4) of UPPCR
reg_val = ioread32( upp_base + UPPCR );
reg_val |= 0x00000010;
iowrite32( reg_val, upp_base + UPPCR );
//
// wait at least 200 clock cycles
// (SPRUGJ5B.PDF, 2.6.1.4)
mdelay( 200 ); // abitrary choice of 200ms
// SPRUH77A.PDF, Section 33.2.7.1.4 --AND--
// SPRUGJ5B.PDF, 2.6.1.4
// clear SWRST bit (bit 4) of UPPCR
reg_val = ioread32( upp_base + UPPCR );
reg_val &= 0xffffffef;
iowrite32( reg_val, upp_base + UPPCR );
}
//SPRUGJ5B.PDF, Section 2.6.1.5
static void upp_config( void )
{
int32_t regVal;
//-------------------------------------------------------------------------
// UPPCTL - UPP Interface Channel Settings....SPRUH77A.PDF, Section 33.3.4.
//
// - DATA and XDATA Pin assignments to Channels A & B:
// Refer to SPRUGJ5B.PDF, Table 3:
//
// ____PHYSICAL_PINS___|____CHANNEL_ASSIGNMENT___
// * DATA[7:0] | A[7:0]
// * DATA[15:8] | B[7:0]
//-------------------------------------------------------------------------
regVal = 0;
regVal |= 1 << 17; // IWA - CHANNEL A 8/16bit MODE: Set Channel A to 16 bit mode
iowrite32( regVal, upp_base + UPCTL );
//-------------------------------------------------------------------------
// UPPICR - signal enable, signal inversion, clk div (tx only), etc.
// SPRUH77A.PDF, Section 33.3.5
//-------------------------------------------------------------------------
regVal = 0; //Channel A: START is active-high
regVal |= 1<<3; //Channel A:STARTA is honored in Rev Mode
regVal |= 1<<4; //Channel A:ENABLEA is honored in Rev Mode
regVal |= 1<<12; //Channel A:(CLKINVA) Signal on rising edge of clock
regVal |= 1<<13; //Channel A:(TRISA) pins are High-impedence while idle
iowrite32( regVal, upp_base + UPICR );
//-------------------------------------------------------------------------
// UPPIVR - Idle Value Register
// SPRUH77A.PDF, Section 33.3.5
//-------------------------------------------------------------------------
regVal = 0;
regVal |= 0xab00; //Channel B Idle Value
regVal |= 0x00cd; //Channel A Idle Value
iowrite32( regVal, upp_base + UPIVR );
//-------------------------------------------------------------------------
// UPTCR - i/o tx thresh (tx only), dma read burst size
//-------------------------------------------------------------------------
regVal = 0x00000003; //DMA Channel I READ-threshold. 256 bytes (max)
iowrite32(regVal, upp_base + UPTCR );
}
//SPRUGJ5B.PDF, Section 2.6.1.6
static void upp_interrupt_enable( void )
{
int32_t regVal, status;
// Register the ISR before enabling the interrupts....
status = request_irq( UPP_INTERRUPT, upp_ISR_handler, 0, "upp_ISR", 0 );
if( status < 0 )
{
return;
}
// clear all interrupts
iowrite32( UPIES_MASK, upp_base + UPIEC );
//------------------------------------------------------------------------
//Dumping Registers again for debugging purpose
//dump_Channel_regs();
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// UPIES - Interrupt Enable. Interrupt events will generate a CPU interrupt
//-------------------------------------------------------------------------
// regVal = 0x17; //Enable ALL interrupts (but EOWI) for DMA Channel I
//regVal |= 0x17 << 8; //Enable ALL interrupts (but EOWQ) for DMA Channel Q
regVal = UPIES_MASK;
iowrite32( regVal, upp_base + UPIES );
}
//SPRUGJ5B.PDF, Section 2.6.1.7
static void upp_enable( void )
{
int32_t reg_val;
// set EN bit in UPPCR.
// The EN bit (effectively disabling the UPP peripheral)...
// was cleared in "upp_swrst()" function
reg_val = ioread32( upp_base + UPPCR );
reg_val |= 1 << 3;
iowrite32( reg_val, upp_base + UPPCR );
}
static void upp_disable( void )
{
int32_t reg_val;
reg_val = ioread32( upp_base + UPPCR );
reg_val &= ~(1 << 3); //0xfffffff7;
iowrite32( reg_val, upp_base + UPPCR );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////MODIFIED BY: SHEHRYAR ; 25-NOV-2014 4:40pm PST (+5.00 GMT)///////////////////
static void setpin_GPIO (void)
{
int32_t reg_val=0;
if ((gpio_base = ioremap(DA850_GPIO_BASE, SZ_4K)) == 0)
{
return;
}
//reg_val = ioread32(gpio_base + SET_DATA67);
reg_val |= (1<<6); ///Set Pin 6 of Bank 6 GP6P6 to 1 to drive GPIO high
iowrite32(reg_val,gpio_base + SET_DATA67);
}
static void clrpin_GPIO(void)
{
int32_t reg_val=0;
if ((gpio_base = ioremap(DA850_GPIO_BASE, SZ_4K)) == 0)
{
return;
}
//reg_val = ioread32(gpio_base + CLR_DATA67);
/*reg_val |= ~(1<<0);
reg_val |= ~(1<<1);
reg_val |= ~(1<<2);
reg_val |= ~(1<<3);
reg_val |= ~(1<<4);*/
reg_val |= (1<<6); //Set Pin 6 of bank 6 GP6P6 of CLR_DATA67 Register to High to drive GPIO signals low
iowrite32(reg_val,gpio_base + CLR_DATA67);
}
///////Function to set DIR to 1 for GP6P5//////////////////////////////////////////////////////////////
static void Config_GPIO(void)
{
int32_t reg_val;
if ((gpio_base = ioremap(DA850_GPIO_BASE, SZ_4K)) == 0)
{
return;
}
//set dir
reg_val = ioread32(gpio_base + DIR67);
reg_val &= ~(1<<0);
reg_val &= ~(1<<1);
reg_val &= ~(1<<2);
reg_val &= ~(1<<3);
reg_val &= ~(1<<4);
reg_val &= ~(1<<6);
iowrite32(reg_val,gpio_base + DIR67);
printk(KERN_INFO "DIR67 => [0x%08X]\n", reg_val);
//set to high
reg_val = ioread32(gpio_base + SET_DATA67);
reg_val |= (1<<0);
reg_val |= (1<<1);
reg_val |= (1<<2);
reg_val |= (1<<3);
reg_val |= (1<<4);
iowrite32(reg_val,gpio_base + SET_DATA67);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//SPRUGJ5B.PDF, Section 2.6.1.8
// Return false on error
static bool upp_mem_alloc( void )
{
//rxBuf2 = kcalloc( 1 , UPP_BUF_SIZE, GFP_KERNEL | GFP_DMA );
rxBuf = kcalloc( 1 , UPP_BUF_SIZE, GFP_KERNEL | GFP_DMA );
if (!rxBuf) //|| (!rxBuf2)
{
return false;
}
return true;
}
static void upp_program_DMA_channelA( void )
{
while ( ioread32( upp_base + UPIS2 ) & 0x00000002 );
//------------------------------------------------------------------------
// Channel A (Rx), (DMA Channel I) //27th Nov 2014 - 11:08 am
//------------------------------------------------------------------------
iowrite32( rxBuf, upp_base + UPID0);
iowrite32( ( (UPP_RX_LINE_COUNT << 16) | UPP_RX_LINE_SIZE ), upp_base + UPID1);
iowrite32( UPP_RX_LINE_OFFSET, upp_base + UPID2);
}
//------------------------------------------------------------------------
// User-mode functions read/write/open/close, etc.
//------------------------------------------------------------------------
int upp_open( struct inode *iPtr, struct file *fPtr )
{
int minor,major;
read_pending = 0;
minor=iminor(iPtr);
major=imajor(iPtr);
printk( KERN_INFO "upp_open: MAJOR(%d), MINOR(%d)\n", major, minor);
upp_disable();
upp_enable();
return 0;
}
////////////////////////////////////////////////////////////READ FUNCTION STARTS HERE!!!!!!////
/*-------------------------------------------------------------------------------------------*/
//int count_missing_data=0;
//static int read_flag =0;
ssize_t upp_read( struct file *fPtr, char __user *buffer, size_t size, loff_t *offset )
{
int readBytes = 0;
int retVal=0;
void *bPtr = (void *)buffer;
if (!bPtr) {return -1; printk(KERN_INFO "ERROR: bPtr not initilized\n");}
printk(KERN_INFO "Reading %d Bytes ...\n",size );
while (readBytes<size)
{
//read_flag+=1;
read_pending = 0;
//mdelay(10);
memset(rxBuf,255,8192);
//memset(rxBuf2,128,8192);
upp_program_DMA_channelA();
clrpin_GPIO();
wait_event_interruptible( read_queue, read_pending > 0 );
while ( ioread32( upp_base + UPIS2 ) & 0x00000001 )
{
printk (KERN_INFO "DMA IS STILL ACTIVE! \n");
}
setpin_GPIO(); // Set High
retVal = copy_to_user(bPtr,rxBuf,read_pending);
if(retVal)
{
printk(KERN_INFO "ERROR: Copy to user failed!\n");
return readBytes;
}
readBytes += read_pending;
bPtr += 8192;
} //end of while loop
printk(KERN_INFO"\nRead [%d] Bytes.\n",readBytes);
printk(KERN_INFO"END OF WINDOW (EOWI) INTERRUPT Count = [%d]\n", EOWI_Count);
printk(KERN_INFO"DMA UNDERRUN OR OVERFLOW (UORI) Interrupt Count = %d\n", UORI_count);
return readBytes;
//read_flag += 1;
//mdelay(9);
}
//////////////////////////////////////////////READ() FUNCTION ENDS HERE!!!!!!///////////////////////////
/*---------------------------------------------------------------------------------------------------*/
int upp_release( struct inode *iPtr, struct file *fPtr )
{
return 0;
printk(KERN_INFO "upp_release completed.\n");
}
static struct cdev *UPP_cdev;
static dev_t UPP_MajorMinorNumbers;
struct file_operations upp_fops = {
.owner = THIS_MODULE,
//.llseek = no_llseek,
//.poll = upp_poll,
.read = upp_read,
//.write = upp_write,
//.ioctl = upp_ioctl,
.open = upp_open,
//.release = upp_release,
};
/*
* Return ZERO on success.
*
*/
static int __init upp_init(void)
{
int retVal;
//printk(KERN_INFO "Entering upp_init().\n");
//SPRUGJ5B.PDF, Section 2.6.1.8
// I'm doing this out-of-order...If the mem-allocation fails,
// there is no sense in doing anything else, except to bail early...
if (upp_mem_alloc() == false)
{
printk(KERN_INFO "******ERROR: Could not allocate buffers. Bailing!******\n");
return -1;
}
//--------------------------------------------------------
//--------------------------------------------------------
//SPRUGJ5B.PDF, Section 2.6.1.1
upp_pin_mux_init();
printk(KERN_INFO "upp_pin_mux_init()...OK.\n");
//SPRUGJ5B.PDF, Section 2.6.1.2.
upp_power_and_clocks();
printk(KERN_INFO "upp_power_and_clocks()...OK.\n");
//SPRUGJ5B.PDF, Section 2.6.1.3, 2.6.1.4
upp_swrst();
printk(KERN_INFO "upp_swrst()...OK.\n");
//SPRUGJ5B.PDF, Section 2.6.1.5
upp_config();
printk(KERN_INFO "upp_config()...OK.\n");
//SPRUGJ5B.PDF, Section 2.6.1.6
upp_interrupt_enable();
printk(KERN_INFO "upp_interrupt_enable()...OK.\n");
//SPRUGJ5B.PDF, Section 2.6.1.7
upp_enable();
printk(KERN_INFO "upp_enable()...OK.\n");
//---------------------------SETTING GPIOS----------------
Config_GPIO();
//--------------------------------------------------------
setpin_GPIO(); // Set High
UPP_MajorMinorNumbers = MKDEV( 0, 0);
if ( (retVal = alloc_chrdev_region( &UPP_MajorMinorNumbers, 0, 1, "UPP" )) < 0)
{
printk(KERN_INFO "ERROR: Major/Minor number allocation failed.\n");
return retVal;
}
UPP_cdev = cdev_alloc();
UPP_cdev->ops = &upp_fops;
UPP_cdev->owner = THIS_MODULE;
if (cdev_add( UPP_cdev, UPP_MajorMinorNumbers, 1) != 0)
{
printk(KERN_INFO "ERROR: UPP driver NOT loaded. CDEV registration failed.\n");
}
else
{
printk(KERN_INFO "\nUPP Major: %d , Minor: %d \n", MAJOR(UPP_MajorMinorNumbers), MINOR(UPP_MajorMinorNumbers));
}
printk("UPP driver (1.8.0 - 5/January/2015) succesfully installed.\n");
return 0;
}
/*
*
*
*
*/
static void __exit upp_exit(void)
{
uint32_t regVal;
printk(KERN_INFO "Exiting..Initializing upp_exit call......\n");
// SPRUH77A.PDF, Section 33.2.7.1.1, Table 33-12.
// clear EN bit of UPPCR to disable the UPP.
regVal = ioread32( upp_base + UPPCR );
regVal &= 0xfffffff7;
iowrite32( regVal, upp_base + UPPCR );
free_irq( UPP_INTERRUPT, 0);
if (rxBuf)
{
kfree( rxBuf );
rxBuf = 0;
}
/*if (rxBuf2)
{
kfree(rxBuf2);
rxBuf2=0;
}*/
cdev_del( UPP_cdev );
unregister_chrdev_region( UPP_MajorMinorNumbers, 1);
clrpin_GPIO(); //added 2-Dec-2014
printk(KERN_INFO "UPP driver unloaded (Successful Exit). \n");
}
MODULE_AUTHOR("Ali Shehryar & Umair Ali");
MODULE_DESCRIPTION("OMAP-L138/AM-1808 UPP bus driver");
MODULE_LICENSE("GPL");
module_init(upp_init)
module_exit(upp_exit)
With the code, I have made a tester application that writes a .264 based output file consisting of data acquired from my custom board which I call upp_tester.cpp :
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <string.h>
int main(int argc, char **argv )
{
int count = 0;
const int BytesToRead = 8192*4; //32kB
int bytesRead = -1;
int bytesWritten = -1 ;
int upp_fd,out_fd;
char readBuff[BytesToRead] = {0,};
int k = 0;
readBuff[BytesToRead]={'\0'};
upp_fd = open( "/dev/upp", O_RDWR);
out_fd = open( "output_upp.264", O_RDWR|O_CREAT);
for(count = 0; count<100; count++)
{
if (upp_fd == -1)
{
fprintf( stderr , "OPEN failed [%d] - UPP\n" , errno );
if (errno == 2)
{
fprintf( stderr , "NOTE! Check that /dev/upp actually exists, and has the right permissions \n");
}
return errno;
}
if (out_fd == -1)
{
fprintf( stderr , "OPEN /output_upp failed [%d] - Out.dat\n" , errno );
}
//fprintf( stderr , "UPP TESTER Version 1.0.17\n\n" );
for (k=0;k<32;k++)
{
bytesRead = read( upp_fd, readBuff, sizeof (readBuff));
fprintf( stderr , "READ [%d] bytes out of [%d] bytes\n" , bytesRead , sizeof(readBuff) );
bytesWritten = write( out_fd, readBuff, bytesRead );
fprintf( stderr , "WROTE [%d] bytes out of [%d] bytes\n" , bytesWritten , sizeof(readBuff) );
}
}
close(upp_fd);
close(out_fd);
return 0;
}
Now when I explore the output file, I see that a lot of bytes are missing which I usually set to 255 using memset. This is because the core I have programmed for my dsp processor for the tester file is set to throw fixed data from 0-99. What could be causing this problem. I am a total newbie to device drivers and kernel level programming so any help would be deeply appreciated.
In case you would like to submit the driver to upstream (which actually a right way to go), you probably may contact with TI guys who are working with DaVinci boards. I assume you already googled the link DaVinci Wiki.
Regarding to your driver it's hard to check due to its code style. Moreover you may check modern kernel APIs for stuff you are trying to program manually (voltage regulators, clocks, pin control, and so on). For many basic devices there are already drivers and setup. Also you have to describe you board configuration in device tree. Usually it means to create an additional (to the common) piece of configuration and put it under arch/arm/boot/dts/. There you may find da850 predefined data bases.

Undefined reference to `usbInit' in C AVR

I use v-usb library for my project.
I wrote code and i want compile it, but unfortunately I have an error which I'm unable to resolve.
Here is my screen-shot:
Description Resource Path Location Type
make: *** [USB_module.elf] Error 1 USB_module C/C++ Problem
undefined reference to `usbInit' main.c /USB_module C/C++ Problem
undefined reference to `usbMsgPtr' main.c /USB_module C/C++ Problem
undefined reference to `usbPoll' main.c /USB_module C/C++ Problem
This situation is for me strange because i have in header this:
#include "usbconfig.h"
#include "usbdrv/usbdrv.h"
#include "usbdrv/oddebug.h"
And usbdrv/usbdrv.h defines the USBpoll function:
Shouldn't the compiler be able to compile it?
Here is my project: http://goo.gl/P6ujK
And here is my entire workspace directory: http://minus.com/mbhTkJuvOK#1
Here is my code: main.c:
/*
* main.c
*
* Created on: 25-01-2012
* Author: Bordeux
*/
#define F_CPU 12000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include "usbconfig.h"
#include "usbdrv/usbdrv.h"
#include "usbdrv/oddebug.h"
#define DDS1_SDA (1<<1) //PORTB1
#define DDS_SCL (1<<3) //PORTB3
#define DDS_UPDATE (1<<4) //PORTB4
static uchar usb_val;
USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len) //sends len bytes to DDS_SDA
{
uchar i;
uchar b;
uchar adr=0;
while (len!=0)
{
b=1;
for (i=0; i<8; i++)
{
if (b & data[adr])
{
PORTB = (PORTB | DDS1_SDA) & ~DDS_SCL;
PORTB = PORTB | DDS_SCL;
}
else
{
PORTB = PORTB & (~DDS1_SDA & ~DDS_SCL);
PORTB = PORTB | DDS_SCL;
}
b=b<<1;
}
len--;
adr++;
}
if (usb_val)
{
PORTB = PORTB | DDS_UPDATE;// update DDS
PORTB = PORTB & ~DDS_UPDATE;
}
return 1;
}
USB_PUBLIC uchar usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
static uchar replyBuf[3];
usbMsgPtr = replyBuf;
if(rq->bRequest == 0) // ECHO value
{
replyBuf[0] = data[2]; // rq->bRequest identical data[1]!
replyBuf[1] = data[3];
return 2;
}
if(rq->bRequest == 1) // set port directions
{
// DDRA = data[2];
DDRB = data[3];
DDRD = data[4] & (~USBMASK & ~(1 << 2)); // protect USB interface
return 0;
}
if(rq->bRequest == 2) // read ports
{
// replyBuf[0] = PINA;
replyBuf[1] = PINB;
replyBuf[2] = PIND;
return 3;
}
if(rq->bRequest == 3) // read port states
{
// replyBuf[0] = PORTA;
replyBuf[1] = PORTB;
replyBuf[2] = PORTD;
return 3;
}
if(rq->bRequest == 4) // set ports
{
// PORTA = data[2];
PORTB = data[3];
PORTD = data[4];
return 0;
}
if(rq->bRequest == 5) // use usbFunctionWrite to transfer len bytes to DDS
{
usb_val = data[2]; // usb_val!=0 => DDS update pulse after data transfer
return 0xff;
}
if(rq->bRequest == 6)
{
PORTB = PORTB | DDS_UPDATE; // issue update pulse to DDS
PORTB = PORTB & ~DDS_UPDATE;
return 0;
}
replyBuf[0] = 0xff; // return value 0xff => command not supported
return 1;
}
int main(void)
{
wdt_enable(WDTO_1S); // set Watchdog Timer
odDebugInit();
PORTB=0xe0; // Set PortB 0-4 zero
DDRB=0x1f; // Set PORTB 0-4 output
PORTD = 0; /* no pullups on USB pins */
DDRD = ~USBMASK & ~(1 << 2); /* all outputs except USB data and PD2 = INT0 */
usbInit();
sei();
for(;;) /* main event loop */
{
wdt_reset(); // restart watchdog timer
usbPoll();
}
return 0;
}
solution:
mv usbdrv.c usbdrv.cpp
or compile with avr-g++
You need to link against whatever file supplies usbInit etc., from the looks of your screen shots you've shown the file usbdrv.c, but not actually compiled/linked it into your project. Only usbdrv.h is showing in the tree view.
#includeing the header file shows the compiler the declaration of the function, you need to make sure it sees the definition somewhere too.
you could also have included usbdrv.h in extern "C":
extern "C" {
#include "usbdrv.h";
}

Resources