How to "call" driver ioctl from another driver? - driver

A user space program can modify the RTS pin of a serial port / UART using an ioctl call. For example:
int RTS_flag = TIOCM_RTS;
ioctl(fd, TIOCMBIS, &RTS_flag);
ioctl(fd, TIOCMBIC, &RTS_flag);
Suppose I want to control the RTS pin from a driver. Is it possible to "call" the driver holding the tty and ask it to control the pin for me? (Rather than figuring out the control registers of the specific device and reading/writing bytes, not to mention instantly supporting all the UART chips supported by the kernel drivers).
What's the proper way of going about that?
For example, in myDriver:
static const struct file_operations ecp_fileOps =
{
.owner = THIS_MODULE,
.unlocked_ioctl = my_ioctl,
.write = 0,
.read = 0,
.poll = 0,
.open = lirc_dev_fop_open,
.release = lirc_dev_fop_close,
.llseek = no_llseek,
};
static long ecp_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
"Call" tty ioctl function...
}
}
OS INFO
# uname -a
Linux ecp 4.4.127-1.el6.elrepo.i686 #1 SMP Sun Apr 8 09:44:43 EDT 2018 i686 i686 i386 GNU/Linux
# cat /etc/centos-release
CentOS release 6.6 (Final)

Related

Enabling bus mastering/BMDMA in gem5 FS mode

I am building a custom full system configuration (largely influenced by ARM in configs/FSConfig.py) and am running into an issue where the kernel hangs on boot, being unable to access the disk image to mount the root filesystem. Looking at the kernel boot logs and gem5 call trace, I strongly suspect the culprit has to do with this:
[ 0.000005] ata_piix 0000:00:01.0: BMDMA: BAR4 is zero, falling back to PIO
In other words, while a standard ARM FS mode simulation will enable bus mastering on the simulated gem5 (PIIX) IDE controller and use DMA to access the disk, my simulation reverts to PIO instead. The PCI node of my device tree is the one from ARM’s vexpress (aarch64) dtb. My PCI host/IDE controller setup is also similar to ARM’s setup:
self.cf0 = CowIdeDisk(driveID='master')
self.cf0.childImage(mdesc.disk())
self.pci_host = GenericPciHost(conf_base=0x30000000, conf_size=’256MB’, confi_device_bits=12, pci_pio_base=0x2f000000)
self.pci_ide = IdeController(disks=[self.cf0], pci_dev=1, pci_bus=0)
pci_devices.append(self.pci_ide)
…
self.pci_host.pio = self.iobus.master
for dev_id, dev in enumerate(pci_devices):
dev.host = self.pci_host
dev.pio = self.iobus.master
dev.dma = self.iobus.slave
The gem5 call trace includes the following (no methods from CowDiskImage are called):
IdeController::Channel::accessCommand: offset = 6, size = 1, read = 0
IdeDisk::updateState: action = 4.
IdeDisk::writeCommand: Write to disk at offset: 0x6 data 0xa0
IdeController::dispatchAccess: Write from offset: 0x2f000016 size: 0x1 data: 0xa0
IdeDisk::readControl: Read to disk at offset: 0x2 data 0x40
IdeController::dispatchAccess: Read from offset: 0x2f000022 size: 0x1 data: 0x40
IdeDisk::writeControl: Write to disk at offset: 0x2 data 0xa
IdeController::dispatchAccess: Write from offset: 0x2f000022 size: 0x1 data: 0xa
I have already verified that my kernel includes drivers for the PIIX, legacy ATA controllers, and BMDMA. I have also attempted to change the BAR4 value of the IDE controller directly in the system configuration file and update the device tree with a dma-ranges field for the PCI node. None of these solutions worked.
TL;DR: How do I ensure that my full system configuration supports and enables bus mastering for the IDE controller? Is there anything special I need to add to the device tree binary?

ESP8266 Fatal exception (0) using NodeMCU

When i boot ESP8266 i'm getting on my arduino MEGA serial monitor.
Fatal exception (0): e2= 0d00l(xp00v0xao1,00e0c pe80c00d0x:2= 0d00l(xp00v0xao1,00e0c pe80c00d0x:2= 0d00l(xp00v0xao1,00e0c e 0xp0= 0e)02,0d00a 0e00c00Fic00= 0p0e 0xp0= 0e)02
If i do a hard reset than it prints
Jan 8 2013,rst cause:4, boot mode:(3,6) wdt reset load 0x40100000, len 28740, room 16 tail 4 chksum 0xcd load 0x3ffe8000, len 2888, room 4 tail 4 0xeotail 0 chks
I used NodeMcu flasher nodemcu_integer_0.9.5_20150318.bin and NodeMCU 0.9.5 build 20150318 powered by Lua 5.1.4. I'm using arduino UART (serial monitor) to talk to ESP8266. BAUD RATE : 115200 FLASH SIZE : 4MB FLASH SPEED : 40MHz SPI : DIO Module is powered with apt power (separate power supply)
Here's my connections:
//////////////////////////////////////////////////////////////////////////////
/////// CONNECTIONS ////////
/////////////////////////////////////////////////////////////////////////////
/*
ESP8266 VCC -> BeagleBone 3.3
ESP8266 GND -> Common GND (Arduino & BeagleBone)
ESP8266 CH_PD -> 3K resistor -> VCC
ESP8266 RST -> VCC or pin 13(arduino)
GPIO CAB BE LEFT OPEN OR TIED HIGH
ESP8266 Tx -> pin2 (Arduino software serial Rx)
ESP8266 Rx <- Voltage Divider <- pin3 (Arduino software serial Tx)
*/
Here's my code
#define esp8266 Serial2
#define CH_PD Vcc // but needs a narrow low pulse
#define speed8266 9600 // This is the speed that worked with my ESP8266
void setup()
{
esp8266.begin (speed8266);
Serial.begin(9600);
reset8266(); // Pin CH_PD need a reset before start communication
}
void loop()
{
while(esp8266.available())
{ Serial.write(esp8266.read()); }
while(Serial.available())
{ esp8266.write(Serial.read()); }
}
/*************************************************/
// Reset funtion to accept communication
void reset8266 ()
{
pinMode(CH_PD, OUTPUT);
digitalWrite(CH_PD, LOW);
delay(300);
digitalWrite(CH_PD, HIGH);
}
Here are some snaps of the configuration i did in NodeMCU ( i had already tried with different baud rates)
Advanced Configuration
Configuration
If you are getting fatal error exception like this:
Exception (3):
epc1=0x401003e9 epc2=0x00000000 epc3=0x00000000 excvaddr=0x4000cbd9 depc=0x00000000
In infinite loop in your serial monitor of arduino IDE .
then goto this link download the software and follow the procedure and erase the flash memory to solve the error.
This does not solve fatal error that occurs due to your program but in case your device goes in such condition that it can’t be able to access program memory then it will work and try atleast one time to solve the problem.
This is the procedure to hard reset the nodemcu
( https://www.youtube.com/watch?v=MHrm7axsImI&t=146s )
Step :
Install latest python version in you pc.(https://www.python.org/downloads )
Open cmd prompt as administrator .
Go to c/program files or program files (x86)->python (your version)->Script. For this type (cd c/program files (x86)/python(your version)/Script) then press enter .
Now type (pip install esptool).
Now download ESPlorer ( https://esp8266.ru/esplorer/ ) version(Download ESPlorer.zip (v 0.2.0-rc6)) and extract the file and open executable jar file .
Now goto nodemcu firmware site (https://github.com/nodemcu/nodemcu-firmware/releases ) and from download file (nodemcu_float_0.9.6-dev_20150704.bin ) and copy this file into the c/program files (x86)/python(your version)/Script folder .
Now in cmd prompt just type.
esptool.py --port COM(your port no.) --baud 115200 erase_flash
And press enter.
Note : you can see your port no. into the device manager .
For NODEMCU users who face this issue
This needs to be done only once (first time you connect nodemcu to PC)
Download and run the 32 or 64 bit flasher*:
32 bit: https://github.com/nodemcu/nodemcu-flasher/blob/master/Win32/Release/ESP8266Flasher.exe
64 bit: https://github.com/nodemcu/nodemcu-flasher/blob/master/Win64/Release/ESP8266Flasher.exe
Select the download button on github and open file once downloaded.
Select the chip port from the previous step (Com 6 for me), and then select flash (this should only have to be done once) close flash program once completed. Process is completed when you get the green checkmark in the bottom left hand corner.
PS: make sure you disconnect and re-connect the nodemcu once done
REFERENCE: https://www.instructables.com/NodeMcu-ESP8266-First-Time-Setup-With-Arduino-IDE/

UART data error when using uart.alt(1)

I am trying to acquire rs232 data from a device connected to the ESP8266 (data will then be sent our via http/wifi).
I am using max3232 IC to provide the necessary 3.3v TTL to the ESP8266.
I have have connected the max3232 (pin 12) to GPIO pin 13 (rx) on the ESP8266 (I am only receiving data not sending data, so only the rx pin is connected).
The code i am using:
--
--file: test2.lua
--
tst2 = require "tst2"
tst2.start()
--tst2.lua (testing script)
local module = {}
function module.start()
print("in tst2.start")
uart.alt(1) --use alt GPIO pin 13 (Rx)
uart.setup(0, 9600,8, uart.PARITY_NONE, uart.STOPBITS_1,0)
uart.on("data",10,
function(data)
file.open("data.tmp", "w+")
file.writeline("starting")
for i=1,10 do
file.writeline(string.byte(string.sub(data,i,i)) )
end
file.writeline("from uart: ", data)
file.writeline("finished")
file.close()
end, 0)
uart.alt(0) --switch back to standard Rx/Tx pins
end
return module
The rs232 device connected to the ESP8266 is putting out a single alphabetic character every 3 seconds, however the data written to file (data.tmp) is as follows
starting
10
13
10
13
10
13
10
13
10
13
from uart:
finished
file.close()
Problems:
1- The rs232 device is not issuing any newln or cr characters, but these are appearing in the data file.
2- the string "file.close()" is being written to the data file, and looks like it is the actual lua command that follows the final file.writeline command.
3- the alphabetic data is not appearing in the data file.
4- switching back to the standard uart pins via uart.alt(0) does not work (the ESP8266 must be rebooted - this is not a major issue as the standard uart pins are only used during debugging).
I am writing the rs232 data to a file instead of simply printing it out on the screen (I am using ESPlorer v0.2.0) because the uart.alt(1) command redirects the serial port to the alternative ESP8266 gpio pins.
I think I am doing something fundamentally wrong with the uart set up, but i can't tell what it is.
SOLVED:
It appears that you can't connect the ESP8266 to both the serial port for debugging (e.g. the serial port on a pc running ESPlorer) and also have the alternate serial pins (ESP8266 GPIO 13 and 15) connected (to an external serial device) at the same time.
The nodemcu uart.alt() function does not appear to "turn off" the standard serial i/o pins.
Disconnecting the pc from the standard serial i/o pins solved the problem (debugging becomes an issue, but there are work-arounds to resolve this).
(updated) one workaround is to use a simple telnet server to interact with the lua interpreter. you can either connect the ESP8266 to your wifi router or, even better, set it up as an access point (AP) so that all you have to do is to connect your computer to it and then simply telnet in (to the gateway's IP). so, in addition to the telnet code, you'll need set up the AP in your init.lua. full code for the telnet server and the AP setup is below. A nice benefit is that I can program and monitor the ESP8266 from my phone using an off-the-shelf telnet app!
jj = [[
sock = 22 -- just a placeholder, so it stays global. may not be needed.
-- use sock:send("hello") to insert your own custom output to the client.
telnet_srv = net.createServer(net.TCP, 180)
telnet_srv:listen(2323, function(socket)
local fifo = {}
local fifo_drained = true
local function sender(c)
if #fifo > 0 then
c:send(table.remove(fifo, 1))
else
fifo_drained = true
end
end
local function s_output(str)
table.insert(fifo, str)
if socket ~= nil and fifo_drained then
fifo_drained = false
sender(socket)
end
end
sock = socket -- make the socket globally available.
node.output(s_output, 0) -- re-direct output to function s_ouput.
socket:on("receive", function(c, l)
node.input(l) -- works like pcall(loadstring(l)) but support multiple separate line
end)
socket:on("disconnection", function(c)
node.output(nil) -- un-regist the redirect output function, output goes to serial
end)
socket:on("sent", sender)
print("Welcome to NodeMCU world.")
end)
]]
file.open("telnet.lua", "w")
file.write(jj)
file.close()
jj = [[
wifi.setmode(wifi.STATIONAP);
wifi.ap.config({ssid="ESPtest",pwd=""});
print("Server IP Address:",wifi.ap.getip())
dofile("telnet.lua")
]]
file.open("init.lua","w")
file.write(jj)
file.close()
node.restart()
output:
Server IP Address: 192.168.4.1 255.255.255.0 192.168.4.1
>

Beaglebone Black with MIDI input (via USB) -> can't detect proper port

A few days back I wrote question regarding MIDI and ALSA, but I've since solved the problem and run into a new one.
the context in short:
I have a Beaglebone Black with debian 7.5 on it.
My host is a 32bit Ubuntu 14.10 installation.
I'm using Qt4.8.6 for arm cross-compilation.
I am trying create an application which uses a touchscreen and also reads MIDI input from a keyboard. I've used the following tutorial (http://embedded.von-kannen.net/2014/05/21/qt-4-8-6-on-beaglebone-black/) to install Qt embedded so I can crosscompile to my beaglebone (Tutorial needs some fixes, I've got a 'fixed' doc ready if anyone needs one) and the following one to compile ALSA for use on an ARM MPU: omappedia.org/wiki/ALSA_Setup
Basically after I finally got the program building and deploying onto my beaglebone black it couldn't find the port it needs to receive the MIDI signals.
I'm using a MidiMate II to connect the MIDI device I'm using to a USB port on a HUB in my Beaglebone Black.
I have the following code to check for available ports (C++):
RtMidiIn *midiin = 0;
// RtMidiIn constructor
try {
midiin = new RtMidiIn();
}
catch ( RtMidiError &error ) {
error.printMessage();
exit( EXIT_FAILURE );
}
// Check inputs.
unsigned int nPorts = midiin->getPortCount();
qDebug() << "\nThere are " << nPorts << " MIDI input sources available.\n";
std::string portName;
for ( unsigned int i=0; i<nPorts; i++ ) {
try {
portName = midiin->getPortName(i);
}
catch ( RtMidiError &error ) {
error.printMessage();
delete midiin
}
std::cout << " Input Port #" << i+1 << ": " << portName << '\n';
}
I can confirm that the MidiMate functions properly with Ubuntu. As running the application on desktop receives values just fine. I'm not certain of functionality on Debian for the BeagleBone.
The above code tells me there are no available input sources when ran on the Beaglebone, as opposed to the 2 available input sources when ran on both Ubuntu and Windows desktops.
my question:
How can I get my Beaglebone to detect the port that I need for reading the live MIDI input?
edit:
plugging the midimate into the beaglebone generates a midi1 entry int the /dev/ list.
however I don't know what and how to do with it.
the RtMidi function I use can only accept an unsigned integer as input so I can't provide the string "midi1" as an argument :(
Your distribution does not load the snd-seq and snd-seq-midi kernel modules when booting, and has no mechanism to load them on demand either.
Add them to the /etc/modules file.

Reserving a portion of SDRAM to pass data between U-Boot and the Linux Kernel

How can I reserve a portion of SDRAM, say 4 bytes, to pass a flag between U-Boot and the Linux kernel so that this reserved memory location is not initialized by the linker and the value preserved after a warm boot? I'm trying to avoid using bootargs to minimize wear of the NAND flash used in an embedded application. My question could be considered an extension to the solution provided by:
How to detect cold boot versus warm boot on an ARM processor?
I have built u-boot.lds with the linker script below and built it with:
-fno-zero-initialized-in-bss without success.
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
cpu/arm926ejs/start.o (.text)
*(.text)
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : { *(.data) }
. = ALIGN(4);
.got : { *(.got) }
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .;
_U_BOOT_FLAG = .; . = . + 4;
.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
_end = .;
}
Any ideas?
There is already a method to pass data between U-Boot and the Linux ARM kernel. It's called the ATAG memory list. Information such as usable memory regions, and board information are passed from U-Boot to the Linux ARM kernel using this data list. You could define a custom ATAG for your data. In U-Boot, add your routine to build your ARM tag in lib_arm/armlinux.c. Then ATAGs are processed in arch/arm/kernel/setup.c.
For documentation see Section 8 of this or this alt site.
ADDENDUM
Links to the referenced ATAG documentation are tenuous (even Google has a bad link).
Try searching for the actual name of the document, which is "Booting ARM Linux" by Vincent Sanders.
Currently there's a copy in Google's cache of the simtec site, and a broader search turned up a translation in Korean(?).
Another or an earlier version (?) (but seems to have been updated) by Russel King on ARM booting is here.
If you want to go by the global-variable approach in How to detect cold boot versus warm boot on an ARM processor? :
You can force that global variable to be in a specific ELF section (see http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Variable-Attributes.html) , and then in the linker script set that section to a specific address.
If you have good ld-script skills, you could even get the linker to initialize all bss sections except that one :)

Resources