If I call ecrt_slave_config_reg_pdo_entry to create a domain offset, I get the message:
Failed to register PDO entry: No such file or directory
I believe that I have to call ecrt_slave_config_pdos, which I am not at the moment. However, I do not understand why I have to call it. In my case, the slave I like to talk to is already connected to the bus. If I enter ec cstruct -p [SLAVE_POS] in a terminal, I get the PDO layout.
me#here:~$ ec cstruct -p 1
/* Master 0, Slave 1, "..."
* Vendor ID: 0x...
* Product code: 0x...
* Revision number: 0x...
*/
ec_pdo_entry_info_t slave_1_pdo_entries[] = {
{0x6040, 0x00, 16},
...
};
ec_pdo_info_t slave_1_pdos[] = {
{0x1600, 2, slave_1_pdo_entries + 0},
...
};
ec_sync_info_t slave_1_syncs[] = {
{0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},
...
{0xff}
};
Why can I get all input arguments for ecrt_slave_config_pdos from the terminal command, but EtherCat cannot (or does not want to) configure the slave itself? Can the slave configuration be automated?
You can use the functions ecrt_master_get_slave(), ecrt_master_get_sync_manager(), ecrt_master_get_pdo(), and (of course) ecrt_master_get_pdo_entry() to retrieve all the necessary information. ecrt_master_get_sync_manager(), e.g., will not set the PDO information, but will return the number of PDO positions for a synchronization manager.
So something like that works for me (error code checks left out for the sake of clarity):
ecrt_master_get_slave(..., &slaveInformation);
// For every synchronization manager...
for (size_t syncIndex = 0; syncIndex < slaveInformation.sync_count; ++syncIndex) {
ecrt_master_get_sync_manager(..., &syncInformation);
ecrt_slave_config_sync_manager(...);
// For every PDO field...
for (size_t pdoIndex = 0; pdoIndex < syncInformation.n_pdos; ++pdoIndex) {
ecrt_master_get_pdo(..., &pdoInformation);
ecrt_slave_config_pdo_assign_add(...);
// For every entry in the pdo field...
for (size_t entryIndex = 0; entryIndex < pdoInformation.n_entries; ++entryIndex) {
ecrt_master_get_pdo_entry(..., &entryInformation);
ecrt_slave_config_pdo_mapping_add(...);
}
}
}
This, however, does not really answer the question why (or if) all this is necessary. To be specific on cleaner: It would be nice, if the Pyramid of Doom could be avoided. Especially, since I am telling the slave something it told me one line before.
Related
I have an imbedded Tcl interpreter and want to redirect its stderr and stdout to a console widget in the application.
Using a chan push command for stderr seems to work (not much testing yet), like explained here:
TCL: Redirect output of proc to a file
I could have a file with the required tcl namespace definition, etc, and do a Tcl_Eval to source that script after creating an interp with Tcl_CreateInterp.
Can I do the same thing using Tcl C library calls instead of running the Tcl commands via a Tcl_Eval?
To implement a channel transformation in C, you first have to define a Tcl_ChannelType structure. Such a structure specifies a name for the transformation and pointers to functions for the different operations that may be done on a channel. Next, you implement the functions that perform those operations. The most important ones are inputProc and outputProc. You also have to implement a watchProc. The pointers for other operations can be set to NULL, if you don't need them.
For your example it may look something like:
static const Tcl_ChannelType colorChannelType = {
"color",
TCL_CHANNEL_VERSION_5,
NULL,
ColorTransformInput,
ColorTransformOutput,
NULL, /* seekProc */
NULL, /* setOptionProc */
NULL, /* getOptionProc */
ColorTransformWatch,
NULL, /* getHandleProc */
NULL, /* close2Proc */
NULL, /* blockModeProc */
NULL, /* flushProc */
NULL, /* handlerProc */
NULL, /* wideSeekProc */
NULL,
NULL
};
Then, when you want to push the transformation onto a channel:
chan = Tcl_StackChannel(interp, &colorChannelType, clientData,
Tcl_GetChannelMode(channel), channel);
For a complete example from the Tcl sources, see tclZlib.c
Not really an answer to my question, but maybe it will help someone to see what works by using a Tcl_Eval to show the tcl code that does the redirection.
proc redir_stdout {whichChan args} {
switch -- [lindex $args 0] {
initialize {
return {initialize write finalize}
}
write {
::HT_puts $whichChan [lindex $args 2]
}
finalize {
}
}
}
chan push stderr [list redir_stdout 1]
chan push stdout [list redir_stdout 2]
Both the chan push commands use the same proc, but pass an different identifier (1 or 2) to indicate whether stdout or stderr was the originator of the output.
HT_puts is an extension provided by the C code:
Tcl_CreateObjCommand(interp,"HT_puts",putsCmd,(ClientData) NULL,NULL);
int TclInterp::putsCmd(ClientData ,Tcl_Interp *,int objcnt,Tcl_Obj * CONST *objv)
{
if (objcnt != 3)
return TCL_ERROR;
int length;
int whichChan;
Tcl_GetIntFromObj(interp,objv[1],&whichChan);
//qDebug() << "Channel is $whichChan";
QString out =Tcl_GetStringFromObj(objv[2],&length);
QColor textColor;
if (whichChan==1)
textColor = QColor(Qt::red);
else
textColor = QColor(Qt::white);
console->putData(out.toUtf8(),textColor);
//qDebug() << out;
return TCL_OK;
}
Text forwarded from stderr gets colored red and text from stdout gets colored white.
And, as I mentioned above, each subsequent command that gets executed via Tcl_Eval needs to have the Tcl_Eval return value processed something like this:
if (rtn != TCL_OK)
{
QString output = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
console->putData(output.toUtf8(),QColor(Qt::red));
//qDebug("Failed Tcl_Eval: %d \n%s\n", rtn,
}
To get what's normally printed to stderr by tclsh on a TCL_ERROR into the console (instead of the app's stderr).
I was planning to do the equivalent in C to eliminate the need to run Tcl code in the interpreter for the redirect. But, really there's no need for that.
The Tcl_Eval that does the redirection is done right after doing the Tcl_CreateInterp. Any subsequent Tcl_Evals using that interp will have stdout and stderr redirected to my application's console.
Besides, I'm having trouble understanding how to use Tcl_StackChannel and can't find an example I can follow.
Honestly, can't say that I completely understand the Tcl implementation. I made some assumptions on what gets passed to the proc used in the "chan push" command based on the referenced thread.
It looks like the proc is called with the list specified in the chan push command AND an args list. The first element of the args list is a name like "write" or "initialize". The third element looks like the string to be printed.
Still trying to find a definition of what's passed without having to dig into something like namespace ensemble.
So, it's likely that this Tcl code isn't the best implementation but it's working so far (with limited testing).
I'm converting a pure-Python module to a C-extension to familiarize myself with the C API.
The Python implementation is as follows:
_CRC_TABLE_ = [0] * 256
def initialize_crc_table():
if _CRC_TABLE_[1] != 0: # Safeguard against re-initialization
return
# snip
def calculate_crc(data: bytes, initial: int = 0) -> int:
if _CRC_TABLE_[1] == 0: # In case user forgets to initialize first
initialize_crc_table()
# snip
# additional non-CRC methods trimmed
My C-extension thus far works:
#include <Python.h>
static Py_ssize_t CRC_TABLE_LEN = 256;
PyObject *_CRC_TABLE_;
static PyObject *method_initialize_crc_table(PyObject *self, PyObject *args) {
// snip
}
static PyMethodDef module_methods[] = {
{"initialize_crc_table", method_initialize_crc_table, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
void _allocate_table_() {
_CRC_TABLE = PyList_New(CRC_TABLE_LEN);
PyObject *zero = Py_BuildValue("i", 0);
for (int i = 0; i < CRC_TABLE_LEN; i++) {
PyList_SetItem(_CRC_TABLE_, i, zero);
}
}
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef module_utilities = {
PyModuleDef_HEAD_INIT,
"utilities",
NULL,
-1,
module_methods,
};
PyMODINIT_FUNC PyInit_utilities() {
PyObject *module = PyModule_Create(&module_utilities);
_allocate_table_();
PyModule_AddObject(module, "_CRC_TABLE", _CRC_TABLE_);
return module;
}
#else
PyMODINIT_FUNC initutilities() {
PyObject *module = Py_InitModule3("utilities", module_methods, NULL);
_allocate_table_();
PyModule_AddObject(module, "_CRC_TABLE", _CRC_TABLE_);
}
I am able to access utilities._CRC_TABLE_ from the C-extension in the interpreter and values match the Python-equivalent when invoking utilities.intialize_crc_table.
Now I'm trying to call initialize_crc_table at the start of calculate_crc, performing the same check as used in the Python implementation. I'm returning None for now:
static PyObject *method_calculate_crc(PyObject *self, PyObject *args) {
if (!(uint)PyLong_AsUnsignedLong(PyList_GetItem(_CRC_TABLE_, (Py_ssize_t) 1))) {
PyObject *call_initialize_crc_table = PyObject_GetAttrString(self, "initialize_crc_table");
PyObject_CallObject(call_initialize_crc_table, NULL);
Py_DECREF(call_initialize_crc_table);
}
Py_RETURN_NONE;
}
I've added this to module_methods[] and it compiles without warnings or errors. When I run this method within the interpreter, I get a segfault. I assume it's because self isn't the module as an object.
I can do this as an alternative, which appears to work without issue:
static PyObject *method_calculate_crc(PyObject *self, PyObject *args) {
if (!(uint)PyLong_AsUnsignedLong(PyList_GetItem(_CRC_TABLE_, (Py_ssize_t) 1))) {
method_initialize_crc_table(self, NULL);
}
Py_RETURN_NONE;
}
However, I am not certain if I should be passing self, NULL, or something else to the method.
What is the proper way of invoking method_initialize_crc_table from method_calculate_crc?
There was a "gotcha" here that I must clarify on. While the code was intended for Python 3, development was initially done in Python 2 as the development files were not yet available on the machine I was using. This shed some light on some differences in how each version handles things. David's comments helped lead to this clarification.
If a method is defined as METH_VARARGS but is defined for a module (versus a class), Python 2 does not pass anything for the PyObject *self parameter. This is noted in the documentation but is easy to overlook if you're not careful. Python 3, however, does pass a pointer to the module. As DavidW recommended, I implemented a global variable to hold a reference to the module. Assuming his claims of Python handling the de-referencing at exit are correct, we can safely use this for accessing module global attributes.
With our issue of PyObject *self solved, we no longer get a segfault. We can then address the question of which approach is (seemingly more) correct for calling a method within the local scope of the module. Do we do this:
if (/* conditional */)
PyObject_CallMethod(module, "initialize_crc_table", NULL);
Or this:
if (/* conditional */)
method_initialize_crc_table(self, args, kwargs);
Benchmarks seem to provide an answer here. Using Python's built-in timeit module, we can see a very clear difference in terms of performance. Note that so far in our implementation, .calculate_crc accesses ._CRC_TABLE_ and checks if it's initialized, but no processing occurs. Performance compared to Python 2 and 3 were identical and thus ignored.
The command is as follows:
python3 -m timeit "import utilities; utilities.calculate_crc(0)"
PyObject_CallMethod: 874 nsec per loop
method_initialize_crc_table: 44.3 usec per loop
Using the PyObject_ function is reported as 50x faster, quite a significant difference. Benchmarks alone do not facilitate what is "more correct" but with no clear guidance it may be a sufficient justification for our use. Therefore, I will be using PyObject_ calls for this project.
I'm gonna to read/write under the modbus-tcp specification.
So, I'm trying to code the client and server in the linux environment.
(I would communicate with the windows program(as a client) using the modbus-tcp.)
but it doesn't work as I want, so I ask you here.
I'm testing the client code for linux as a client and the easymodbus as a server.
I used the libmodbus code.
I'd like to read coil(0x01) and write coil(0x05).
When the code is executed using the libmodbus, 'ff' is printed out from the Unit ID part.(according to the manual, 01 should be output for modbus-tcp.
I don't know why 'ff' is printed(photo attached).
Wrong result:
Expected result:
'[00] [00] .... [00]' ; Do you know where to control this part?
Do you have or do you know the sample code that implements the 'read/write' function using the libmodbus?
please let me know the information, if you know that.
ctx = modbus_new_tcp("192.168.0.99", 502);
modbus_set_debug(ctx, TRUE);
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
tab_rq_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
memset(tab_rq_bits, 0, nb * sizeof(uint8_t));
tab_rp_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
memset(tab_rp_bits, 0, nb * sizeof(uint8_t));
nb_loop = nb_fail = 0;
/* WRITE BIT */
rc = modbus_write_bit(ctx, addr, tab_rq_bits[0]);
if (rc != 1) {
printf("ERROR modbus_write_bit (%d)\n", rc);
printf("Address = %d, value = %d\n", addr, tab_rq_bits[0]);
nb_fail++;
} else {
rc = modbus_read_bits(ctx, addr, 1, tab_rp_bits);
if (rc != 1 || tab_rq_bits[0] != tab_rp_bits[0]) {
printf("ERROR modbus_read_bits single (%d)\n", rc);
printf("address = %d\n", addr);
nb_fail++;
}
}
printf("Test: ");
if (nb_fail)
printf("%d FAILS\n", nb_fail);
else
printf("SUCCESS\n");
free(tab_rq_bits);
free(tab_rp_bits);
/* Close the connection */
modbus_close(ctx);
modbus_free(ctx);
return 0;
That FF you see right before the Modbus function is actually correct. Quoting the Modbus Implementation Guide, page 23:
On TCP/IP, the MODBUS server is addressed using its IP address; therefore, the
MODBUS Unit Identifier is useless. The value 0xFF has to be used.
So libmodbus is just sticking to the Modbus specification. I'm assuming, then, that the problem is in easymodbus, which is apparently expecting you to use 0x01as the unit id in your queries.
I imagine you don't want to mess with easymodbus, so you can fix this problem pretty easily from libmodbus: just change the default unit id:
modbus_set_slave(ctx, 1);
You could also go with:
rc = modbus_set_slave(ctx, MODBUS_BROADCAST_ADDRESS);
ASSERT_TRUE(rc != -1, "Invalid broadcast address");
to make your client address all slaves within the network, if you have more than one.
You have more info and a short explanation of where this problem is coming from in the libmodbus man page for modbus_set_slave function.
For a very comprehensive example, you can check libmodbus unit tests
And regarding your question number 5, I don't know how to answer it, the zeros you mean are supposed to be the states (true or false) you want to write (or read) to the coils. For writing you can change them with the value field of function modbus_write_bit(ctx, address, value).
I'm very grateful for your reply.
I tested the read/write function using the 'unit-test-server/client' code you recommended.
I've reviewed the code, but there are still many things I don't know.
However, there is an address value that acts after testing each other with unit-test-server/client code and there is an address value that does not work
(Do you know why?).
-Checked and found that the UT_BITS_ADDRESS (address value) value operates from 0x130 to 0x150
-'error Illegal data address' occurs at values below -0x130 and above 0x150
-The address I want to read/write is 0x0001 to 0x0004(Do you know how to do?).
I want to know how to process and transmit data like the TX part of the right picture.
enter image description here
I'm running both client and server in my Linux environment and I'm doing read/write testing.
Among the wrong pictures...[06][FF]... <-- I want to know how to modify FF part (to change the value to 01 as shown in the picture)
enter image description here
and "modbus_set_slave" is the function for modbus rtu?
I'd like to communicate PC Program and Linux device in the end.
so Which part do I use that function?
I thanks for your concern again.
I've been porting newlib to my very small kernel, and I'm stumped: whenever I include a function that references a system call, my program will page fault on execution. If I call a function that does not reference a system call, like rand(), nothing will go wrong.
Note: By include, I mean as long as the function, e.g. printf() or fopen(), is somewhere inside the program, even if it isn't called through main().
I've had this problem for quite some time now, and have no idea what could be causing this:
I've rebuilt newlib numerous times
Modified my ELF loader to load the
code from the section headers instead of program headers
Attempted to build newlib/libgloss separately (which failed)
Linked the libraries (libc, libnosys) through the ld script using GROUP, gcc and ld
I'm not quite sure what other information I should include with this, but I'd be happy to include what I can.
Edit: To verify, the page faults occurring are not at the addresses of the failing functions; they are elsewhere in the program. For example, when I call fopen(), located at 0x08048170, I will page fault at 0xA00A316C.
Edit 2:
Relevant code for loading ELF:
int krun(u8int *name) {
int fd = kopen(name);
Elf32_Ehdr *ehdr = kmalloc(sizeof(Elf32_Ehdr*));
read(fd, ehdr, sizeof(Elf32_Ehdr));
if (ehdr->e_ident[0] != 0x7F || ehdr->e_ident[1] != 'E' || ehdr->e_ident[2] != 'L' || ehdr->e_ident[3] != 'F') {
kfree(ehdr);
return -1;
}
int pheaders = ehdr->e_phnum;
int phoff = ehdr->e_phoff;
int phsize = ehdr->e_phentsize;
int sheaders = ehdr->e_shnum;
int shoff = ehdr->e_shoff;
int shsize = ehdr->e_shentsize;
for (int i = 0; i < pheaders; i++) {
lseek(fd, phoff + phsize * i, SEEK_SET);
Elf32_Phdr *phdr = kmalloc(sizeof(Elf32_Phdr*));
read(fd, phdr, sizeof(Elf32_Phdr));
u32int page = PMMAllocPage();
int flags = 0;
if (phdr->p_flags & PF_R) flags |= PAGE_PRESENT;
if (phdr->p_flags & PF_W) flags |= PAGE_WRITE;
int pages = (phdr->p_memsz / 0x1000) + 1;
while (pages >= 0) {
u32int mapaddr = (phdr->p_vaddr + (pages * 0x1000)) & 0xFFFFF000;
map(mapaddr, page, flags | PAGE_USER);
pages--;
}
lseek(fd, phdr->p_offset, SEEK_SET);
read(fd, (void *)phdr->p_vaddr, phdr->p_filesz);
kfree(phdr);
}
// Removed: code block that zeroes .bss: it's already zeroed whenever I check it anyways
// Removed: code block that creates thread and adds it to scheduler
kfree(ehdr);
return 0;
}
Edit 3: I've noticed that if I call a system call, such as write(), and then call printf() two or more times, I will get an unknown opcode interrupt. Odd.
Whoops! Figured it out: when I map the virtual address, I should allocate a new page each time, like so:
map(mapaddr, PMMAllocPage(), flags | PAGE_USER);
Now it works fine.
For those curious as to why it didn't work: when I wasn't including printf(), the size of the program was under 0x1000 bytes, so mapping with only one page was okay. When I include printf() or fopen(), the size of the program was much bigger so that's what caused the issue.
I'm particularly interesting in doing this on Linux, regarding Java programs. There are already a few questions that say you have no control from Java, and some RFEs closed by Sun/Oracle.
If you have access to source code and use a low-level language, you can certainly make the relevant system calls. However, sand-boxed systems - possibly without source code - present more of a challenge. I would have thought that a tool to set this per-process or an kernel parameter are able to control this from outside the parent process. This is really what I'm after.
I understand the reason why this is the default. It looks like some version of Windows may allow some control of this, but most do not. I was expecting Linux to allow control of it, but seems like it's not an option.
Provided you have sufficient privileges, you could simply call setaffinity before execing in the child. In other words, from
if (fork() == 0)
execve("prog", "prog", ...);
move to use
/* simple example using taskset rather than setaffinity directly */
if (fork() == 0)
execve("taskset", "taskset", "-c", "0-999999", ...);
[Of course using 999999 is not nice, but that can be substituted by a program which automatically determined the number of cpus and resets the affinity mask as desired.]
What you could also do, is change the affinity of the child from the parent, after the fork(). By the way, I'm assuming you're on linux, some of this stuff, such as retrieving the number of cores with sysconf() will be different on different OS's and unix flavors.... The example here, gets the cpu of the parent process and tries to ensure all child processes are scheduled on a different core, in round robin.
/* get the number of cpu's */
numcpu = sysconf( _SC_NPROCESSORS_ONLN );
/* get our CPU */
CPU_ZERO(&mycpuset);
sched_getaffinity( getpid() , sizeof mycpuset , &mycpuset);
for(i=0 ; i < numcpu ; i++ )
{
if(CPU_ISSET( i, &mycpuset))
{
mycpu = i;
break;
}
}
//...
while(1)
{
//Some other stuff.....
/* now the fork */
if((pid = fork()) == 0)
{
//do your child stuff
}
/* Parent... can schedule child. */
else
{
cpu = ++cpu % numcpu;
if(cpu == mycpu)
cpu = ++cpu % numcpu;
CPU_ZERO(&mycpuset);
CPU_SET(cpu,&mycpuset);
/*set processor affinity*/
sched_setaffinity(pid, sizeof mycpuset, &mycpuset );
//any other father stuff
}
}