I have connected GPIO Pin 17(in WiringPi Pin17 = Pin0) of my raspberry pi 1 with an interrupt source (an IR-LEDemitter/receiver which triggers an interrupt whenever the IR ray gets interrupted by some obstacle). For setting up the ISR, I have been using the WiringPi library (I have already tried it with the pigpio library as well, but I have the same problem there as well).
To verify that I am actually receiving interrupts on Pin17, I have checked it with my logic analyzer, and there are definitely some interrupts occuring on this pin as you can see:
Here is my code:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <wiringPi.h>
#include "MCP3008Driver.h"
#include "DHT11.h"
#define INT_PIN 0
volatile int eventCounter = 0;
void myInterrupt(void){
printf("hello ISR!\n");
eventCounter++;
}
volatile sig_atomic_t stopFlag = 0;
static void stopHandler(int sign) { /* can be called asynchronously */
stopFlag = 1; /* set flag */
}
int main(void) {
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
// sets up the wiringPi library
if (wiringPiSetup () < 0) {
printf("Unable to setup wiring pi\n");
fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror
(errno));
return 1;
}
// set Pin 17/0 to generate an interrupt on high-to-low transitions
// and attach myInterrupt() to the interrupt
if(wiringPiISR(INT_PIN, INT_EDGE_FALLING, &myInterrupt) < 0){
printf("unable to setup ISR\n");
fprintf(stderr, "Unable to setup ISR: %s\n", strerror(errno));
}
DHT11_data data;
configureSPI();
while(1){
if(stopFlag){
printf("\n Ctrl-C signal caught! \n");
printf("Closing application. \n");
return 0;
}
//read_dht_data(&data);
int analogBoiler = readChannel(0);
int analogHeater = readChannel(1);
int analogPress = readChannel(2);
int analogACS712 = readChannel(3);
int analogDynamo = readChannel(4);
printf("Channel 0 / Boiler = %f\n", evaluateChannelValue(ePT100_BOILER, analogBoiler));
printf("Channel 1 / Heater = %f\n", evaluateChannelValue(ePT100_HEATER, analogHeater));
printf("Channel 2 / Pressure = %f\n", evaluateChannelValue(ePRESS, analogPress));
printf("Channel 3 / Power ACS712 = %f\n", evaluateChannelValue(eACS712, analogACS712));
printf("Channel 4 / Power Dynamo = %f\n", evaluateChannelValue(eDYNAMO, analogDynamo));
//printf("Humidity Environment: %f\n", data.humidity);
//printf("Temperature (Celsius) Environment: %f\n", data.temp_celsius);
// display counter value every second.
printf("%d\n", eventCounter);
sleep(5);
}
return 0;
}
The methods wiringPiSetup and wiringPiISR are successfully called and are not returning an error.
I am building this example the the following linking options: -lwiringPi -lm -lpthread. Maybe I am missing a linking option?
I have been using this code here as a reference. So what am I doing wrong here? Thank you for any advice you can give me!
I'm not entirely sure why but I found that removing the unary operator in front of the function call input to wiringPiISR solved my problems.
So instead of calling
wiringPiISR(INT_PIN, INT_FALLING_EDGE, &MyInterrupt)
call
wiringPiISR(INT_PIN, INT_FALLING_EDGE, MyInterrupt)
My guess is that this has something to do with the fact the wiringPiISR is taking that argument as pointer (*function) so putting the address of call in front of it causes something weird to happen when it goes to try and call the MyInterrupt function, for me it caused my program to crash!
Hope this helps / maybe someone else will be able to elaborate more on why this would happen.
Related
I've written a simple program, use ucontext library. However, a signal SIGSEGV (address boundary error) occurred. The running env is MacOS. I do not know what's wrong I made?
Updated Here: Version 2
As #Jeremy suggest, we could use static on main_context and work_context. However, if we change work_context to an array, it still failed
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <sys/time.h>
#include <unistd.h>
#define _XOPEN_SOURCE 600
#include "ucontext.h"
static ucontext_t main_context;
static ucontext_t work_context[3]; // version 2: from ucontext_t to an array
static void counter()
{
for (int c = 0; ; c++) {
fprintf(stderr, "c = %d\n", c);
sleep(5); // avoid busy loop
}
}
static ucontext_t* make_context1(ucontext_t *ucp, void (*func)())
{
getcontext(ucp);
sigemptyset(&ucp->uc_sigmask);
void *sp = malloc(SIGSTKSZ);
if (sp == NULL) {
fprintf(stderr, "malloc failed\n");
exit(-1);
}
ucp->uc_stack = (stack_t) { .ss_sp = sp, .ss_size = SIGSTKSZ, .ss_flags = 0 };
ucp->uc_link = &main_context;
makecontext(ucp, func, 0);
return ucp;
}
int main() {
printf("start\n");
make_context1(work_context, counter);
make_context1(work_context+1, counter); // added in version 2
make_context1(work_context+2, counter); // added in version 2
swapcontext(&main_context, work_context);
printf("main exit\n");
return 0;
}
For some reason the code runs without crashing if I change these two lines:
ucontext_t main_context;
ucontext_t work_context;
to this:
static ucontext_t main_context;
static ucontext_t work_context;
I'm sure there is a good explanation for this, but I don't know what it is :(
Well, that's simple - SIGSTKSZ is too small of a stack for printf. Increase it. Quadruple it.
Move #define _XOPEN_SOURCE 600 on top of the file. See man feature_test_macros.
Add #include <signal.h> for sigemptyset. Change "ucontext.h" into <ucontext.h>- it's a standard header.
I want to implement a robust timer for an embedded linux application. The goal of this is to control over functions's time of execution and if they take too long, generate an interruption to stop the function's loop.
I searched all over the internet and the firs proposition was to use clock() function.
The solution with clock() function could be :
#include <time.h>
int func(void){
//the starting time of the function
clock_t initial_time;
clock_t elapsed_time;
initial_time = clock()*1000/CLOCKS_PER_SEC;
do{
//some stuff
elapsed_time = clock()*1000/CLOCKS_PER_SEC - initial_time;
}while(elapsed_time < timeout_ms);
printf("time to get command : %ld\n", elapsed_time);
//send an error if a timeout was reached
if(elapsed_time >= timeout_ms){
return -1;
}
else{
return 1;
}
}
But this is not really robust as clock() could cause an overflow in between the function calculations and so, elapsed time will go negative and it will never get out of the loop. This was corrected in the edit section bellow
Second solution was to use the linux kernel timers as following :
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/timer.h>
int g_time_interval = 10000;
struct timer_list g_timer;
void timer_handler (unsigned long data)
{
// do your timer stuff here
}
int init_timer(void)
{
setup_timer(&g_timer, timer_handler, 0);
mod_timer( &g_timer, jiffies + msecs_to_jiffies(g_time_interval));
return 0;
}
void close_timer(void)
{
del_timer(&g_timer);
}
This option seems ok, but I did some research and jiffies (the number of ticks since startup) could overflow too and I don't know if this could affect my usage of this timer. This was corrected in the edit section bellow
Finally, the last option I found was to use timer_create with a signal. As far as I know, this does not has the overflow issue if used with CLOCK_MONOTONIC :
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <stdbool.h>
#define SIG SIG_RTMIN
int init_timer((void *) handler(int, siginfo_t, void*)){
// Establish handler for timer signal
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIG, &sa, NULL) == -1)
printf("Error initializing timer\n");
// Block timer signal temporarily
printf("Blocking signal %d\n", SIG);
sigemptyset(&mask);
sigaddset(&mask, SIG);
// Create the timer
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
}
static void handler(int sig, siginfo_t *si, void *uc)
{
//put a flag to 1 for example
signal(sig, SIG_IGN);
}
//Much other stuff ...
But google told me that we can only set one handler per signal and I dont know if the other processus that are in my linux board use SIG_RTMIN. And as I do not want to break everything by redefining its handler, it is not a convinient solution.
Am I getting something wrong here?
Is there a way to define a timer in linux without having this issues?
Thank you very much to all :)
Edit
Overflow will not cause an issue so option 1 and 2 are valid. Now which one would be the most robust?
Here is the explanation on why I was wrong about overflow. Giving the case where we want to calculate elapsed_time and the maximum clock value is MAX. We have as above :
elapsed_time = clock()*1000/CLOCKS_PER_SEC - initial_time;
Lets rename clock()*1000/CLOCKS_PER_SEC as x. If there is overflow, then theorically theoric_x > MAX, but as there was overflow, x = theoric_x - MAX (hope is clear ':D). So :
elapsed_time = (theoric_x - MAX) - initial_time;
Which can be written as :
elapsed_time = (theoric_x - initial_time) - MAX;
And this is equivalent to : elapsed_time = (theoric_x - initial_time) because substracting the maximum value is like getting back to the same value (it works like modulo). This is ok while the theoric_x is below initial_time + MAX, if we get over, the elapsed time will reset.
I hope it was clear enough.
But google told me that we can only set one handler per signal and I dont know if the other processus that are in my linux board use SIG_RTMIN.
No, it is one handler per signal per process.
That is, having a signal handler for SIGRTMIN in your own program will not interfere with SIGRTMIN handlers of any other processes. Similarly, creating a timer will not affect any other processes' timers either. All you need to worry about, is your own process.
(Technically, there are only a limited number of timers available, so you don't want to create hundreds of them in a single process.)
If you have only one thread in the process, consider the following timeout scheme:
// SPDX-License-Identifier: CC0-1.0
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <stdio.h>
#define TIMEOUT_SIGNAL (SIGRTMIN+0)
#define TIMEOUT_REPEAT_NS 1000000 /* Repeat every millisecond until canceled */
static volatile sig_atomic_t timeout_elapsed; /* Nonzero if timeout has elapsed */
static timer_t timeout_timer;
static void timeout_handler(int signum)
{
(void)signum; /* Silences warning about unused parameter; generates no code. */
timeout_elapsed = 1;
}
static int timeout_init(void)
{
struct sigaction act;
struct sigevent evt;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_handler = timeout_handler;
act.sa_flags = 0;
if (sigaction(TIMEOUT_SIGNAL, &act, NULL) == -1)
return errno;
memset(&evt, 0, sizeof evt);
evt.sigev_notify = SIGEV_SIGNAL;
evt.sigev_signo = TIMEOUT_SIGNAL;
evt.sigev_value.sival_ptr = (void *)0;
if (timer_create(CLOCK_BOOTTIME, &evt, &timeout_timer) == -1)
return errno;
timeout_elapsed = 0;
return 0;
}
static void timeout_cancel(void)
{
struct itimerspec zero;
zero.it_value.tv_sec = 0;
zero.it_value.tv_nsec = 0;
zero.it_interval.tv_sec = 0;
zero.it_interval.tv_nsec = 0;
timer_settime(timeout_timer, 0, &zero, NULL);
}
static void timeout_set(double seconds)
{
struct itimerspec when;
sigset_t mask;
/* Block the timeout signal for now. */
sigemptyset(&mask);
sigaddset(&mask, TIMEOUT_SIGNAL);
sigprocmask(SIG_BLOCK, &mask, NULL);
/* Make sure any previous timeouts have been canceled. */
timeout_cancel();
/* Calculate the next (relative) timeout. */
if (seconds >= 0.000000001) {
long sec = (long)seconds;
long nsec = (long)(1000000000.0*(seconds - (double)sec));
if (nsec < 0)
nsec = 0;
if (nsec > 999999999) {
nsec = 0;
sec++;
}
when.it_value.tv_sec = sec;
when.it_value.tv_nsec = nsec;
} else {
when.it_value.tv_sec = 0;
when.it_value.tv_nsec = 1;
}
/* Set it to repeat, so that it is not easily missed. */
when.it_interval.tv_sec = 0;
when.it_interval.tv_nsec = TIMEOUT_REPEAT_NS;
/* Update the timer. */
timer_settime(timeout_timer, 0, &when, NULL);
/* Clear the flag, and unblock the signal. */
timeout_elapsed = 0;
sigprocmask(SIG_UNBLOCK, &mask, NULL);
}
int main(void)
{
char *line_ptr = NULL;
size_t line_max = 0;
ssize_t line_len;
if (timeout_init()) {
fprintf(stderr, "Cannot set up timeouts: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
timeout_set(5.0);
printf("Please type input lines. This will timeout in five seconds.\n");
fflush(stdout);
while (!timeout_elapsed) {
line_len = getline(&line_ptr, &line_max, stdin);
if (line_len > 0) {
/* Remove trailing newlines */
line_ptr[strcspn(line_ptr, "\r\n")] = '\0';
printf("Read %zd bytes: \"%s\".\n", line_len, line_ptr);
fflush(stdout);
}
}
timeout_cancel();
free(line_ptr);
line_ptr = NULL;
line_max = 0;
printf("Done.\n");
return EXIT_SUCCESS;
}
Compile using gcc -Wall -Wextra -O2 example1.c -lrt -o example1 and run ./example1.
For a multithreaded process, the signal must be delivered to a specific thread, almost always the thread that sets the timeout in the first place. Here, I recommend a different approach: use a helper thread, a list or an array or a binary min-heap of CLOCK_REALTIME absolute times of the respective timeouts, waiting in pthread_cond_timedwait() for the next soonest timeout, or for a signal on the condition variable indicating the timeout list/array/heap has been updated.
POSIX defines clock_gettime. Linux also has extensions for it.
The functions clock_gettime() and clock_settime() retrieve and set the time of the specified clock clockid.
You can simply do the following:
#include <time.h>
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
// Your code here...
clock_gettime(CLOCK_MONOTONIC, &end);
Then end.tv_nsec - start.tv_nsec will provide you nanoseconds with the resolution as specified by clock_getres. Sometimes this is just microseconds or even mere milliseconds. Make sure to check the value and adjust accordingly.
struct timespec res;
clock_getres(CLOCK_MONOTONIC, &res);
switch (res.tv_nsec) {
case 1000: // microseconds
case 10000000: // milliseconds
// cases ...
}
EDIT:
Rereading the original person's post I realize that this doesn't quite answer it. Still, I am leaving it here as it might be useful if applied to the problem. You are free to downvote this if you like as to allow actual answers to rise to the top.
I'm new to pthread and multithreading, i have written a code like that.
#include <pthread.h>
#include <unistd.h>
void *nfc_read(void *arg)
{
int fd = -1;
int ret;
uint8_t read_data[24];
while(1){
ret = read_block(fd, 8, read_data);
if(!ret){
return (void)read_data;
}
}
}
int main(int argc, char *argv[])
{
pthread_t my_thread;
void *returnValue;
pthread_create(&my_thread, NULL, nfc_read, NULL);
pthread_join(my_thread, &returnValue);
printf("NFC card value is : %s \n", (char)returnValue);
printf("other process");
return 0;
}
Until the return value from nfc_read function, as I will have other code I need to run and I don't want to block in main. How can i do that?
This is a sample where a read thread runs concurrently to the "main" thread which is doing other work (in this case, printing dots and sleeping).
To keep things simple, a simulated the reading from an input device with copying a constant string character by character. I guess, this is reasonable as the synchronization of threads is focused.
For the synchronization of threads, I used atomic_bool with atomic_store() and atomic_load() which are provided by the Atomic Library (since C11).
My sample application test-concurrent-read.c:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdatomic.h>
#include <unistd.h>
/* sampe input */
const char sampleInput[]
= "This is sample input which is consumed as if it was read from"
" a (very slow) external device.";
atomic_bool readDone = ATOMIC_VAR_INIT(0);
void* threadRead(void *pArg)
{
char **pPBuffer = (char**)pArg;
size_t len = 0, size = 0;
int c; const char *pRead;
for (pRead = sampleInput; (c = *pRead++) > 0; sleep(1)) {
if (len + 1 >= size) {
if (!(*pPBuffer = realloc(*pPBuffer, (size + 64) * sizeof(char)))) {
fprintf(stderr, "ERROR! Allocation failed!\n");
break;
}
size += 64;
}
(*pPBuffer)[len++] = c; (*pPBuffer)[len] = '\0';
}
atomic_store(&readDone, 1);
return NULL;
}
int main()
{
/* start thread to read concurrently */
printf("Starting thread...\n");
pthread_t idThreadRead; /* thread ID for read thread */
char *pBuffer = NULL; /* pointer to return buffer from thread */
if (pthread_create(&idThreadRead, NULL, &threadRead, &pBuffer)) {
fprintf(stderr, "ERROR: Failed to start read thread!\n");
return -1;
}
/* start main loop */
printf("Starting main loop...\n");
do {
putchar('.'); fflush(stdout);
sleep(1);
} while (!atomic_load(&readDone));
putchar('\n');
void *ret;
pthread_join(idThreadRead, &ret);
/* after sync */
printf("\nReceived: '%s'\n", pBuffer ? pBuffer : "<NULL>");
free(pBuffer);
/* done */
return 0;
}
Compiled and tested with gcc in cygwin on Windows 10 (64 bit):
$ gcc -std=c11 -pthread -o test-concurrent-read test-concurrent-read.c
$ ./test-concurrent-read
Starting thread...
Starting main loop...
.............................................................................................
Received: 'This is sample input which is consumed as if it was read from a (very slow) external device.'
$
I guess, it is worth to mention why there is no mutex guarding for pBuffer which is used in main() as well as in threadRead().
pBuffer is initialized in main() before pthread_create() is called.
While thread_read() is running, pBuffer is used by it exclusively (via its passed address in pPBuffer).
It is accessed in main() again but not before pthread_join() which grants that threadRead() has ended.
I tried to find a reference by google to confirm that this procedure is well-defined and reasonable. The best, I could find was SO: pthread_create(3) and memory synchronization guarantee in SMP architectures which cites The Open Group Base Specifications Issue 7 - 4.12 Memory Synchronization.
I'm running a RT program on BeagleBone Black with Xenomai and trying to figure how to monitor/understand context switches (I know the concept of context switches) so that I can determine when my program (in C using POSIX skin) switches from primary and secondary mode.
Here's the program main_posix.c
#ifndef __XENO_SIM__
#ifndef __KERNEL__
#include <stdio.h>
#define xnarch_printf printf
#endif
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>
#include <pthread.h>
#include <mqueue.h>
#else /* __XENO_SIM */
#include <posix/posix.h>
#endif /* __XENO_SIM */
void warn_upon_switch(){
printf("Switched to Secondary Mode \n");
}
void *threadFunc(void *arg)
{
char *str;
int i = 0;
struct timespec delay, sleep;
unsigned long over;
int ret;
str=(char*)arg;
printf("In thread \n");
sleep.tv_sec = 1;
sleep.tv_nsec = 0;
#ifdef __XENO__
ret = pthread_set_mode_np(0, 0x00040000);
printf("Warn Bit Ret %d\n", ret);
#endif /* __XENO__ */
// run this for some arbitrary time
while(i < 110000000 )
{
clock_nanosleep(CLOCK_REALTIME, 0, &sleep, NULL);
printf("threadFunc says: %s\n",str);
++i;
}
return NULL;
}
int main(void)
{
signal(SIGXCPU, warn_upon_switch);
signal(SIGKILL, warn_upon_switch);
pthread_t pth;
double i = 0;
int ret;
pthread_attr_t tattr;
struct sched_param sparam;
sparam.sched_priority = 99;
ret = pthread_attr_init(&tattr);
printf("Init Return Val %d\n", ret);
ret = pthread_setschedparam(pth,SCHED_FIFO, &sparam);
printf("SetSchedParam Ret Value %d\n", ret);
pthread_create(&pth,&tattr,threadFunc,"foo");
printf("main waiting for thread to terminate...\n");
pthread_join(pth,NULL);
return 0;
}
I'm also monitoring /proc/xenomai/stat continuously through watch
I see that CSWand MSW for PID 3323 changes continuously.
Here's the output of ps -e -o class,rtprio,pri,nice,cmd | grep ./main_posix
The output is as follows
My questions are as follows
How do I know if my program is running in primary or secondary mode?
I get the return value of ret = pthread_setschedparam(pth,SCHED_FIFO, &sparam); as 16 which is EBUSY. Any idea why?
Tried catching the switch signal using signal(SIGXCPU, warn_upon_switch);. The function never gets called.
If the program can be seen in Linux (meaning it gets a PID through the Linux kernel), does it mean its running in secondary mode?
In proc/xenomai/stat, I see two processes for the same program. Is it the main and the thread?
Here are some resources I used
Periodic thread fails real-time in Xenomai
Xenomai clock_nanosleep in POSIX skin jumps to Linux Kernel
http://xenomai.org/2014/08/porting-a-linux-application-to-xenomai-dual-kernel/#Using_the_PTHREAD_WARNSW_bit
http://www.xenomai.org/documentation/xenomai-2.6/html/api/sigxcpu_8c-example.html
It's a FT2232D chip, and the LED is connected to BDBUS6.
The library is less documented than I might like (better than FTDI's own library though, which doesn't even work on modern kernels), the only example code I can find that does this uses a deprecated function (I tried, it doesn't seem to work), and I'm absolutely stumped.
The harder I try with this thing, the more difficult it seems. I'm not looking for someone to do my homework for me so much as I just need a nudge in the right direction. Any help appreciated (even speculative).
Update: I've been trying this, though ftdi_enable_bitbang() is deprecated. The following code compiles, it runs without barfing, but no blinkenlighten. Schematics of the device in question are available at http://www.semtech.com/images/datasheet/sx1211ska_v1_std.pdf , page 23. BDBUS6 and BDBUS7 are hooked up to the LEDs.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <ftdi.h>
#define FTDI_VID 0x0403
#define FTDI_PID 0x6010
static struct ftdi_context ftdic_context;
int main(void) {
int ret;
unsigned int i;
unsigned char c = 0;
// Initialize bitbang.
// ret = ft2232_bb_init();
ftdi_usb_open(&ftdic_context, FTDI_VID, FTDI_PID);
ftdi_set_interface(&ftdic_context, INTERFACE_B);
ftdi_enable_bitbang(&ftdic_context, 0xb0);
// Trying to blink some lights.
printf("\nNow let's try to blinkenlights...\n");
for (i = 0; i < 20; i++) {
c ^= 0x80;
ftdi_write_data(&ftdic_context, &c, 1);
sleep(1);
}
return EXIT_SUCCESS;
}
You need to initialize the ftdi context before you can open a device with it.
ftdi_init(&ftdic_context);
Also you need to set the interface channel before you open the device.
Heres the function I use to set up a ftdi context
int initFTDI(struct ftdi_context * ftdic)
{
unsigned char Mask = 0x1F;
int ret=0;
fprintf(stderr,"start init\n");
ftdi_init(ftdic);
//for multi-channel ftdi chips eg(ft2232)
if(ftdi_set_interface(ftdic,INTERFACE_B))
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if((ret = ftdi_usb_open(ftdic, VID, PID)) < 0){
fprintf(stderr, "unable to open ftdi device: %d (%s)\n", ret, ftdi_get_error_string(ftdic));
return EXIT_FAILURE;
}
if(ftdi_usb_reset(ftdic))
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_usb_purge_buffers(ftdic)) //clean buffers
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_write_data_set_chunksize(ftdic,65536)) //64k transfer size
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_read_data_set_chunksize(ftdic,4096)) //64k transfer size
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_set_event_char(ftdic,false,0)) //disable event chars
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_set_error_char(ftdic,false,0)) //disable error chars
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_set_latency_timer(ftdic,2)) //Set the latency timer to 1mS (default is 16mS)
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_set_baudrate(ftdic,921600))
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_setflowctrl(ftdic,SIO_RTS_CTS_HS)) //set flow control
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if ((ret = ftdi_set_bitmode( ftdic, 0x00, BITMODE_RESET )) < 0 )
{
fprintf(stderr, "can't set bitmode to %x: %d (%s)\n", BITMODE_RESET, ret, ftdi_get_error_string(ftdic));
fprintf( stderr, "RESET\n" );
return EXIT_FAILURE;
}
if ((ret = ftdi_set_bitmode( ftdic, Mask, BITMODE_BITBANG )) < 0 )
fprintf(stderr, "can't set bitmode to %x: %d (%s)\n", BITMODE_BITBANG, ret, ftdi_get_error_string(ftdic));
fprintf( stderr, "RESET\n" );
return EXIT_FAILURE;
}
//fprintf(stderr,"end init\n");
return ret;
}
ftdi_enable_bitbang
is deprecated,
you should use
ftdi_set_bitmode(&ftdic, LED,BITMODE_BITBANG);
instead, see the documentation:
Same Answer as here: I'm having trouble finding example code for libftdi's mpsse (SPI) mode
http://flashrom.org/Downloads
Its mainly MPSSE mode, but it also sets the nCS signal via bitbang command.