I try made mulithread device resource manager with interrupt handler but
this handler is never executed. This same resource manager written as
single-thread device resource manager work fine and handler is executed.
What can be reason that external interrupt is not execute in multi
thread device resource manager. Other interrupt as timers work fine.
In general, this should not matter from the OS/API. That you are
seeing this behaviour almost definitely is a bug in the initiation
of your driver, where going multi-threaded has changed the initiation
path and/or order of operations.
Without seeing/knowing your code, it is almost impossible to give you
a general purpose answer as to what you did wrong. But, one of the
places to start is, do you check the return value on your
InterruptAttach() calls? If they fail, what errno? And start working
from there.
InterruptAttach return positive value.
This is a part of this driver:
Compiled without define MULTI_THREAD working fine but compiletd with
this defien doesn’t work.
#define MULTI_THREAD
#include <errno.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#define THREAD_POOL_PARAM_T dispatch_context_t
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <string.h>
#include <hw/inout.h>
#include <sys/mman.h>
#include <devctl.h>
#include <fcntl.h>
#include <time.h>
#include <arm/pxa250.h>
#include <sys/neutrino.h>
#include <sched.h>
#define ADDR_DEFAULT 0x0C000400
#define IRQ_BASE 126
#define IRQ_DEFAULT 2
#define I2C_RESMGR_NAME “i2c”
volatile uint8_t *control_byte;
volatile uint8_t *data_byte_rx;
volatile uint8_t *data_byte_tx;
struct sigevent event;
char buffor_w[1000];
const struct sigevent * przerwanie (void *argc, int argv);
int odpowiedz (message_context_t *ctp,int code,unsigned flags,void
*handle);
int io_write(resmgr_context_t *ctp,io_write_t *msg,RESMGR_OCB_T *ocb);
void test (void);
static resmgr_connect_funcs_t connect_funcs;
static resmgr_io_funcs_t io_funcs;
static iofunc_attr_t attr;
typedef struct{
unsigned int read_flag :1;
unsigned int req_end :1;
unsigned int enable_end :1;
unsigned int enable_byte :1;
unsigned int irq :2;
unsigned int reset :1;
unsigned int ext_irq :1;
}i2c_control;
union i2c_data_t{
uint8_t value;
i2c_control bits;
};
i2c_data_t i2c_data;
int saved_rcvid;
int main(int argc, char *argv[]) {
resmgr_attr_t resmgr_attr;
dispatch_t *dpp;
int id;
#ifndef MULTI_THREAD
dispatch_context_t *ctp;
#else
thread_pool_t *tpp;
thread_pool_attr_t pool_attr;
#endif
int intrpins[] = {73,72,71};
if((dpp=dispatch_create())==NULL){
fprintf(stderr,"%s: Unable to allocate dispatch
handle.\n",I2C_RESMGR_NAME);
return EXIT_FAILURE;
};
memset(&resmgr_attr,0,sizeof resmgr_attr);
resmgr_attr.nparts_max=1;
resmgr_attr.msg_max_size=2048;
iofunc_func_init(_RESMGR_CONNECT_NFUNCS,&connect_funcs,
_RESMGR_IO_NFUNCS,&io_funcs);
io_funcs.write=io_write;
iofunc_attr_init(&attr,S_IFNAM | 0666,0,0);
id=resmgr_attach(
dpp,
&resmgr_attr,
“/dev/i2c”,
_FTYPE_ANY,
_RESMGR_FLAG_DIR,
&connect_funcs,
&io_funcs,
&attr);
if(id==-1){
fprintf(stderr,"%s: Unable to attach system
name\n",I2C_RESMGR_NAME);
return EXIT_FAILURE;
}
ThreadCtl( _NTO_TCTL_IO, 0 );
if(InterruptAttach (intrpins[IRQ_DEFAULT]+IRQ_BASE, &przerwanie, 0,
0, _NTO_INTR_FLAGS_TRK_MSK)<0)
return EXIT_FAILURE;
control_byte =(uint8_t *)mmap_device_memory(0,1,PROT_NOCACHE |
PROT_READ | PROT_WRITE, 0,ADDR_DEFAULT+4);
data_byte_rx =(uint8_t *)mmap_device_memory(0,1,PROT_NOCACHE |
PROT_READ | PROT_WRITE, 0,ADDR_DEFAULT+0);
data_byte_tx =(uint8_t *)mmap_device_memory(0,1,PROT_NOCACHE |
PROT_READ | PROT_WRITE, 0,ADDR_DEFAULT+0);
if((event.sigev_coid=message_connect(dpp, MSG_FLAG_SIDE_CHANNEL)) == -1) {
fprintf(stderr, “%s: Unable to attach to channel.\n”,I2C_RESMGR_NAME);
return EXIT_FAILURE;
}
if((event.sigev_code=pulse_attach(dpp,MSG_FLAG_ALLOC_PULSE,0,&odpowiedz,NULL))==-1){
fprintf(stderr,"%s: Unable to attach pulse\n",I2C_RESMGR_NAME);
return EXIT_FAILURE;
}
event.sigev_notify=SIGEV_PULSE;
event.sigev_priority=-1;
#ifndef MULTI_THREAD
ctp=dispatch_context_alloc(dpp);
#else
memset(&pool_attr,0,sizeof pool_attr);
pool_attr.handle=dpp;
pool_attr.context_alloc=dispatch_context_alloc;
pool_attr.block_func=dispatch_block;
pool_attr.handler_func=dispatch_handler;
pool_attr.context_free=dispatch_context_free;
pool_attr.lo_water=2;
pool_attr.hi_water=4;
pool_attr.increment=1;
pool_attr.maximum=50;
if((tpp=thread_pool_create(&pool_attr,POOL_FLAG_EXIT_SELF))==NULL)
{
fprintf(stderr,“i2c: Unable to initialize thread pool.\n”);
return EXIT_FAILURE;
};
#endif
if(!fork()){
test();
}
#ifndef MULTI_THREAD
while(1){
if((ctp=dispatch_block(ctp))==NULL){
fprintf(stderr,"%s: Blocking error\n",I2C_RESMGR_NAME);
return EXIT_FAILURE;
}
dispatch_handler(ctp);
}
#else
thread_pool_start(tpp);
#endif
}
const struct sigevent * przerwanie (void *argc, int argv)
{
return (&event);
}
int odpowiedz(message_context_t *ctp,int _code,unsigned flags,void *handle)
{
printf(“Answer\n”);
MsgReply(saved_rcvid,0,NULL,0);
return EOK;
}
int io_write(resmgr_context_t *ctp,io_write_t *msg,RESMGR_OCB_T *ocb)
{
int status;
if((status=iofunc_write_verify(ctp,msg,ocb,NULL))!=EOK)return(status);
if(msg->i.xtype & _IO_XTYPE_MASK != _IO_XTYPE_NONE) return(ENOSYS);
_IO_SET_WRITE_NBYTES(ctp,msg->i.nbytes);
resmgr_msgread(ctp,buffor_w,msg->i.nbytes,sizeof(msg->i));//przepisanie
danych do bufora
if(msg->i.nbytes>0)
ocb->attr->flags |=IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
i2c_data.bits.read_flag =0;
i2c_data.bits.enable_end =0;
i2c_data.bits.enable_byte =0;
i2c_data.bits.req_end =0;
i2c_data.bits.irq=IRQ_DEFAULT;
i2c_data.bits.reset =1;
i2c_data.bits.ext_irq =0;
*control_byte=i2c_data.value; //reset i2c
i2c_data.bits.reset =0;
i2c_data.bits.enable_byte =1;
*control_byte=i2c_data.value; //start i2c
saved_rcvid=ctp->rcvid;
printf(“Wait for interrupt\n”);
return (_RESMGR_NOREPLY);
}
void test (void)
{
int plik;
uint32_t buffor;
int p;
plik=open("/dev/i2c",O_RDWR|O_NONBLOCK);
buffor=0x01;
p=write(plik,&buffor,sizeof(buffor));
if(p<0)printf(“Error:%d\n”,errno);
close(plik);
}
Thanks
Tom