Mounting a file system using a C program - mount

In my initramfs.cpio I have only these directories:
root#localhost extract]# ls
dev init tmp sys
dev has console and sys is empty.
init is a binary corresponding to program that I discussed in Accessing GPIO after kernel boots.
Now in the same GPIO program I would like to write code to mount a /sys. I understand it can be mounted using mount:
mount -t sysfs none /sys
How do I write a C program that will implement the above line. Please note that I do not have a file system; initramfs.cpio has empty folders: /sys, /tmp. I can put more empty folder if required. But I cannot put full file system.
My main intention
To access GPIO using this program or otherwise, but without using a full file system.
I dont need any other thing to run, but just want GPIO access (and LED blink)

You use the mount(2) system call. From the manpage:
SYNOPSIS
#include <sys/mount.h>
int mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data);
So, in your C code, that'd look something like:
#include <sys/mount.h>
/* ... */
void mount_sys() {
if (0 != mount("none", "/sys", "sysfs", 0, "")) {
/* handle error */
}
}
(That last empty string is where you'd pass mount options, but AFAIK sysfs doesn't take any.)

Related

Trying to retrieve data from a serial port but program is stuck at getchar

I am using an embedded system to send data from 25 sensors to a putty terminal on my computer. Works great.
I wanted to add a read from terminal functionality to the embedded system (so I can send commands). So I tried using getchar() to read whatever I would write on my putty terminal. First I just wanted to getchar and print the character back on putty. It kinda works, but my sensor data, which is supposed to print every 500ms, does not print until I type a char in putty. It is as if my code was stuck on getchar() and stuck in a while loop until getchar() reads something.
Here is my forever loop in my int main(). I am not sharing the rest as it is not really needed and too bulky (its just initializing modules). In this loop I am reading a sensor, trying to read from putty, writing to putty, and starting my next scan:
for(;;)
{
CapSense_ProcessAllWidgets(); // Process all widgets
CapSense_RunTuner(); // To sync with Tuner application
read_sensor(curr_elem); //read curr_elem
(curr_elem < RX4_TX4)?(curr_elem++):(curr_elem = 0, touchpad_readings_flag++);
// Here is the part to read I added which blocks until I type in something.
// If I remove this if and all of what's in it, I print to putty every 500ms
if(touchpad_readings_flag)
{
char received_char = getchar();
if (received_char) //if something was returned, received_char != 0
{
printf("%c", received_char);
}
}
//Here I write to putty. works fine when I remove getchar()
if (print_counter_flag && touchpad_readings_flag)
{
print_counter_flag = 0;
touchpad_readings_flag = 0;
for (int i = 0; i < 25; i++)
{
printf("\n");
printf("%c", 97 + i);
printf("%c", val[i] >> 8);
printf("%c", val[i] & 0x00ff); // For raw counts
printf("\r");
}
}
/* Start next scan */
CapSense_UpdateAllBaselines();
CapSense_ScanAllWidgets();
}
Apparently, your getchar() call is blocking unless there is input data to retrieve.
One solution to change this behaviour has been given by another article on different SE board.
Please also note that getchar() is a wrapper for getc() that is acting on stdin as this site1 describes.
For getc() you find further discussions.
In one of those, it is pointed out that some important implementations even wait for a newline character until input is delivered to your function. I think this depends on standard libraries/kind of embedded system you actually use - please check the documentation of your toolchain vendor.2
1
I didn't look up a normative source, this is just my first google hit.
2
The question doesn't specify the kind of embedded system, so a generic answer is wanted instead of a discussion of particular target/toolchain combinations, IMO.

How to integrate attiny85 with source files? Specifically changing Timer0 to Timer1 to avoid conflicting use of timers

I am trying to control a servo motor on a timer using buttons and the ATtiny85. I am able to use the ATtiny to make an LED blink at the push of a button but once I include the servo library my code does not work.
I have tried using the Servo.h library and the Servo8Bit.h library but neither work. I thought that the issue might be coming from one timer being used for two different things so I went into the Servo8Bit.h and Servo8Bit.cpp source files and changed all Timer0 to Timer1 and all TCCR0B to TCCR1B.
I receive these error messages when I try to upload my code:
/private/var/folders/kd/6b3mdhb90xl1rm2j9_dvn7vr0000gn/T/AppTranslocation/EDE8B1E7-9D65-436D-87B1-4534CFB3B4CF/d/Arduino.app/Contents/Java/libraries/Servo8Bit-master/Servo8Bit.cpp: In static member function 'static void ServoSequencer::setupTimerPrescaler()':
/private/var/folders/kd/6b3mdhb90xl1rm2j9_dvn7vr0000gn/T/AppTranslocation/EDE8B1E7-9D65-436D-87B1-4534CFB3B4CF/d/Arduino.app/Contents/Java/libraries/Servo8Bit-master/Servo8Bit.cpp:493:9: error: 'TCCR1A' was not declared in this scope
TCCR1A = 0;
^
/private/var/folders/kd/6b3mdhb90xl1rm2j9_dvn7vr0000gn/T/AppTranslocation/EDE8B1E7-9D65-436D-87B1-4534CFB3B4CF/d/Arduino.app/Contents/Java/libraries/Servo8Bit-master/Servo8Bit.cpp:498:13: error: 'TCCR1B' was not declared in this scope
TCCR1B &= ~(1<< CS02); //clear
^
Using library Servo8Bit-master in folder: /private/var/folders/kd/6b3mdhb90xl1rm2j9_dvn7vr0000gn/T/AppTranslocation/EDE8B1E7-9D65-436D-87B1-4534CFB3B4CF/d/Arduino.app/Contents/Java/libraries/Servo8Bit-master (legacy)
exit status 1
Error compiling for board ATtiny25/45/85.
The expected result is that after uploading the code I will press a button. After a specified amount of time, 10 minutes in this case, the motor should move but the code doesn't even upload.
All you have to do is comment/uncomment the right choice in the header file Servo8Bit.h:
//Options
//pick one, comment out the other one out:
//#define USE_TIMER0
#define USE_TIMER1
and it'll be compiled with correct settings and so on.
You've probably tried to change 0 to 1 everywhere and failed because the timer0 and timer1 aren't the same. The timer1 doesn't have two control registers A and B unlike timer0.

Digispark replacement Wire library

I have a dilemma:
I am trying to get a Digispark to read a BH1750 I2C light sensor and then send the readout via USB. Currently I'm using the DigiUSB library to send to the PC but the sketch is very big (can't implement any of the features I want, using 94% of the flash mem). At the moment it's just sending the value every 0.5 seconds, doing no calculations on it and I have to re-plug the device at boot. I know how to implement these features, it's just that there isn't enough space on the digispark, using both Wire and DigiUSB.
So in order to reduce the size I want to replace Digistump's big Wire library with SoftI2CMaster&SoftWire OR USIWire, both half the size.
I tried two BH1750 I2C libraries (both work fine with Digistump's Wire) but for all four combinations I get the following error:
In file included from C:\Users\xyz\AppData\Local\Temp\arduino_modified_sketch_192160\Echo.ino:8:0:
C:\Users\xyz\Documents\Arduino\libraries\SoftI2CMaster-master/SoftWire.h:101:10: error: conflicting return type specified for 'virtual size_t SoftWire::write(const uint8_t*, size_t)'
size_t write(const uint8_t *data, size_t quantity) {
^
In file included from C:\Users\xyz\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny/Stream.h:24:0,
from C:\Users\xyz\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny/TinyDebugSerial.h:31,
from C:\Users\xyz\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny/WProgram.h:18,
from C:\Users\xyz\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny/Arduino.h:4,
from sketch\Echo.ino.cpp:1:
C:\Users\xyz\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny/Print.h:75:18: error: overriding 'virtual void Print::write(const uint8_t*, size_t)'
virtual void write(const uint8_t *buffer, size_t size);
^
exit status 1
I tried to figure out how to fix this "conflicting return type" error but I couldn't figure out how to do that. Google is often reliable in finding answers but not today.
Any help would be appreciated!

Having trouble programming wifi on esp8266

So I think I'm doing fairly well so far, have the arduino IDE installed, add the ESP8266 module, manage to get an LED blinking on and off. Time to connect to the WIFI and do some stuff.
Unfortunately, it all falls apart then. I get errors about undefined references to wifi_set_opmode, wifi_station_set_config and wifi_station_connect. Now, this isn't my first rodeo with C so I started looking for documentation on these functions and how they are included but can find nothing except people apparently quite happily using them. I've tried adding all sorts of #includes but nothing helps so far. So time to ask for a little help.
Here is the code I am trying to run (pretty uneventful)
#include <user_interface.h>
#define LED_1 13
void setup() {
// put your setup code here, to run once:
pinMode(LED_1, OUTPUT);
const char ssid[32] = "qqqq";
const char password[32] = "wwww";
struct station_config stationConf;
wifi_set_opmode( STATION_MODE );
os_memcpy(&stationConf.ssid, ssid, 32);
os_memcpy(&stationConf.password, password, 32);
wifi_station_set_config(&stationConf);
wifi_station_connect();
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(LED_1, HIGH);
delay(500);
digitalWrite(LED_1, LOW);
delay(500);
}
My board selection is "Generic ESP8266 module"
Here are the errors.
sketch\blinktest.ino.cpp.o:(.text.setup+0x8): undefined reference to `wifi_set_opmode(unsigned char)'
sketch\blinktest.ino.cpp.o:(.text.setup+0x10): undefined reference to `wifi_station_set_config(station_config*)'
sketch\blinktest.ino.cpp.o:(.text.setup+0x14): undefined reference to `wifi_station_connect()'
You need to notice that Arduino is not C, it's based on C++. So add your inclusion like below to use C SDK based functions.
extern "C" {
#include "user_interface.h"
}
Arduino IDE has code examples on menu
File > Examples
There is also example called WiFiWebClient where you need to change only your wifi ssid and password.
Save it to a new folder and you can make http requests to any site on Internet by modifying the address on the example.
Start from the examples of the manufacturer so you don't need to rely on outdated / partial tutorials.

OpenBSD serial I/O: -lpthead makes read() block forever, even with termios VTIME set?

I have an FTDI USB serial device which I use via the termios serial API. I set up the port so that it will time-out on read() calls in half a second (by using the VTIME parameter), and this works on Linux as well as on FreeBSD. On OpenBSD 5.1, however, the read() call simply blocks forever when no data is available (see below.) I would expect read() to return 0 after 500ms.
Can anyone think of a reason that the termios API would behave differently under OpenBSD, at least with respect to the timeout feature?
EDIT: The no-timeout problem is caused by linking against pthread. Regardless of whether I'm actually using any pthreads, mutexes, etc., simply linking against that library causes read() to block forever instead of timing out based on the VTIME setting. Again, this problem only manifests on OpenBSD -- Linux and FreeBSD work as expected.
if ((sd = open(devPath, O_RDWR | O_NOCTTY)) >= 0)
{
struct termios newtio;
char input;
memset(&newtio, 0, sizeof(newtio));
// set options, including non-canonical mode
newtio.c_cflag = (CREAD | CS8 | CLOCAL);
newtio.c_lflag = 0;
// when waiting for responses, wait until we haven't received
// any characters for 0.5 seconds before timing out
newtio.c_cc[VTIME] = 5;
newtio.c_cc[VMIN] = 0;
// set the input and output baud rates to 7812
cfsetispeed(&newtio, 7812);
cfsetospeed(&newtio, 7812);
if ((tcflush(sd, TCIFLUSH) == 0) &&
(tcsetattr(sd, TCSANOW, &newtio) == 0))
{
read(sd, &input, 1); // even though VTIME is set on the device,
// this read() will block forever when no
// character is available in the Rx buffer
}
}
from the termios manpage:
Another dependency is whether the O_NONBLOCK flag is set by open() or
fcntl(). If the O_NONBLOCK flag is clear, then the read request is
blocked until data is available or a signal has been received. If the
O_NONBLOCK flag is set, then the read request is completed, without
blocking, in one of three ways:
1. If there is enough data available to satisfy the entire
request, and the read completes successfully the number of
bytes read is returned.
2. If there is not enough data available to satisfy the entire
request, and the read completes successfully, having read as
much data as possible, the number of bytes read is returned.
3. If there is no data available, the read returns -1, with errno
set to EAGAIN.
can you check if this is the case?
cheers.
Edit: OP traced back the problem to a linking with pthreads that caused the read function to block. By upgrading to OpenBSD >5.2 this issue was resolved by the change to the new rthreads implementation as the default threading library on openbsd. more info on guenther# EuroBSD2012 slides

Resources