|
Richard,
there is something else wrong here.
After I cast (char*) addr it complains abut wrong type.
I need to go and check the ba2str source , perhaps read the results of hci_inquiry
before converting to addr.
It is puzzling why it works on X86, hope it is not yet another "64 bits / 32 bits " issue.
Description Resource Path Location Type
invalid cast from type ‘sockaddr_rc’ to type ‘char*’ CBT.cpp /RPI_BT_CLIENT_ARM_/src/MODULES/M_CBT line 286 C/C++ Problem
|
|
|
|
|
Sorry, I missed the fact that addr is not a pointer (as shown in that link I gave you). Try:
ba2str(&(ii + i)->bdaddr, (char*)&addr);
Or better still use a char array as in the example.
|
|
|
|
|
Mea culpa!
I need to get this client / server code mess under control.
Way too many "addresses" and yet another "shadow" error.
Thanks to all of you it is fixed!
I need to pay better attention to the complier errors - this time it pointed me to "shadows".
Adding the check for it as standard complier option from now on.
Cheers
|
|
|
|
|
I have been writing code using crosscomplier for ARM architecture.
Works as expected. No "cast looses precision " errors.
Now I optioned IDE to change the architecture to X86.
Compiler now complains about
"cast looses precision " .
The complains (too many) are in class I am currently NOT editing.
Is there a option I can set GCC to temporary ignore
"cast looses precision " errors ?
Since the
"cast looses precision " was not present while compiling for ARM it would not hurt to know WHY it fails in X86.
Here is the IDE "error"
Description Resource Path Location Type
cast from ‘uint32_t* {aka unsigned int*}’ to ‘uint32_t {aka unsigned int}’ loses precision [-fpermissive] CBCM2835SPITFT.cpp /RPI_BT_SERVER_X86_/src/MODULES/M_BCM2835_SPI_TFT line 21264 C/C++ Problem
And here ONE of the offending code
bcm2835_peripherals = (uint32_t*) mapmem(
NULL, bcm2835_peripherals_size, _memfd, (uint32_t) bcm2835_peripherals_base);
Cheers
PS I think wholesale "search and replace " is too risky.
PPS Does the architecture - 64 bits on X86 and 32 on ARM matter? - both Linux OS.
|
|
|
|
|
That is because you are trying to cast a pointer to a unint32_t (i.e. a memory address) to an actual uint32_t (i.e. an integer variable). And the pointer may well be larger than 32 bits, so the compiler is warning you that the resulting value may not be what you expect.
|
|
|
|
|
The compiler is complaining that you are casting a pointer to uint32_t (which is 64 bits on Linux built for x86_64) to uint32_t (which is 32 bits). You are losing half of the pointer, which is guaranteed not to end well.
The ARM code was compiled for a 32-bit ARM. If you wish to compile the code for a 64-bit processor, you will have to go carefully through the code, examining each cast and ensuring that it is still valid.
One way to make this (slightly...) less painful would be to use the C99 type uintptr_t (defined in stdint.h) or the C++ type std::uintptr_t (defined in cstdint), which gives you an integer type guaranteed to hold a pointer. You must then ensure that your structures are correctly defined.
All in all, converting a program from 32-bit to 64-bit is a non-trivial task...
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
As Richard and Daniel have pointed out, you get this when trying to convert a pointer to a 32-bit integer in a 64 bit context. You should see the same issue when compiling for 64-bit windows or aarch-64, or indeed any 64-bit architecture.
I would take a look at the definition/implementation of mapmem() . That does not seem to be a linux standard library function, so I can only assume that it is something you have written yourself, or gleaned from the internet. That being the case, in any context, assigning a pointer to an integer is, in general, a sign that you are abusing the language type system. Pointers should remain pointers and ints should remain ints. If you do need to assign a pointer to an int, at least use intptr_t , which will work for most systems. It should certainly work for X86, X86-64, ARM32 and ARM64.
You could add -fpermissive to your complier flags, which will turn the errors intow warnings , but you still have the problem that you are assigning a 64 bit pointer to a 32 bit integer, and are almost certainly going to have serious execution problems.
If you absolutely need to stick with uint32_t for mapmem, then maybe you should compile your X86 code in 32 bit mode, by adding -m32 to the compiler flags. If you do that, you will need to install 32-bit versions, and development versions, of all of the system libraries you are using (libc, bluetooth, etc), and, of course, you will need to recompile your project and all its dependencies in 32 bit mode, too.
|
|
|
|
|
Well that were unexpectedly speedy replies.
I suppose next time I'll sleep on the problem before I post it.
I did find out my mistake - it was actually posted as LAST sentence!
Yes, it is a FFT code I used successfully long time ago and since I am currently not using it , but it is a part of "MY package", I obviously did not pay attention it was written for 32 bits.
After getting about 20 of these error I panic a little, fixing them would keep me from doing the main task. Hence I was looking for a hack.
But it is all fixed and I feel I need to apology for letting the forum to spent much time explaining such "minor" detail as "switching from 32 bits to 64 " in middle of development.
Sorry.
|
|
|
|
|
Well, that's nice. But it bears mentioning that int <-> pointer conversions fail the "smell test". 99.999% of the time integer to pointer conversions are not needed, and point to a misunderstanding of pointers, integers and the relationship between them.
Let me further point out that Raspberry Pi3 and Pi4 are both 64bit chips, and there are various 64-bit Linux distributions available for them. Its not inconceivable that when the Pi5 arrives, it might support 8G RAM (or other features that will only be availble in 64-bit mode), and the default OS will move up to 64 bits. If and/or when that happens, you are going to be back to dealing with "cast looses precision" issues. At least use intptr_t , which is what you should be using in the first place.
|
|
|
|
|
At least use intptr_t, which is what you should be using in the first place. And that is what I am using now.
There is still unanswered question - the inherited ( OK cut and paste) FFT code used 32 bit casts and Rpi 3B HAD no issue with it. I'll go back to that when I am done with code for 64 bit X86.
As far as "8GB ram" - that is little too late for me, but I did learn few tricks cross-compiling.
|
|
|
|
|
I am looking for somebody who can help me to resolve this bluetooth issue.
( I'll ignore any replies NOT discussing / leading to resolution , including insults and RTFM comments )
Included is "bare bones " bluetooth code , I have not included any necessary #includes / library , but if it will help I can add them later if necessary.
I am still having an issue with "address already in use" , BUT my question for now is
why I cannot close and successfully reallocate "socket" ?
I understand that some functions DO NOT generate valid "errno" hence "invalid argument" is really somewhat bogus perror message, however SECOND call to socket should generate "Success" .
Again please concentrate on that for now.
Code output
RPI_BT_SERVER _X86
date version Feb 28 2020
test time 10:17:50
BRAEK @line 333
STATUS allocate socket : Success
STATUS close socket : Invalid argument
STATUS reallocate socket : Invalid argument this is the issue
STATUS bind : Address already in use
STATUS listen : File descriptor in bad state
STATUS accept : File descriptor in bad state
accepted connection from 00:00:00:00:00:00
Code snippet:
<pre> struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int socket_fd, client_fd, bytes_read;
socklen_t opt = sizeof(rem_addr);
socket_fd= socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
perror("STATUS allocate socket ");
close(socket_fd);
perror("STATUS close socket ");
socket_fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
perror("STATUS reallocate socket ");
loc_addr.rc_family = AF_BLUETOOTH;
struct hci_dev_info device_info;
hci_devinfo(0, &device_info);
loc_addr.rc_bdaddr = device_info.bdaddr; loc_addr.rc_channel = (uint8_t) 1;
bind(socket_fd, (struct sockaddr*) &loc_addr, sizeof(loc_addr));
perror("STATUS bind ");
listen(socket_fd, 1);
perror("STATUS listen ");
client_fd = accept(socket_fd, (struct sockaddr*) &rem_addr, &opt);
perror("STATUS accept ");
ba2str(&rem_addr.rc_bdaddr, buf);
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
bytes_read = read(client_fd, buf, sizeof(buf));
if (bytes_read > 0) {
printf("received [%s]\n", buf);
}
close(client_fd);
close(socket_fd);
|
|
|
|
|
The invalid argument message on the close is saying the socket_fd is not a valid socket identifier. So none of the following calls are likely to succeed. Even though perror says success after the socket call, you should check the return value to see what it is.
|
|
|
|
|
Richard,
I have quit checking the actual file descriptor because perror gives a more information when it fails.
But after your post I added such check back.
I also replaced close with shutdown and still getting same results.
Since I still do not trust cerr /perror running on X86 I am going to switch to ARM where the cout / cerr "synchronization " is NOT an issue.
Interestingly , when I check the file descriptor on initial socket allocation , then the reallocated socket file descriptor is different.
I am not sure if that matter, but OS "should" always allocate lowest level file descriptor and that tells me that the original file descriptor is somehow still active.
One small note = I have to make sure perror actually reads the results of the socket call immediately after.
|
|
|
|
|
Vaclav_ wrote: I have quit checking the actual file descriptor because perror gives a more information when it fails.
This could be a problem: perror() prints the associated error string with the current errno , but a successful library call does not reset errno to zero. If you're going to rely on perror() , and by extension errno , you need to make sure you set errrno to zero before any library call that might set errno . Otherwise, you could be getting invalid error information. Every library function I can think of will return a value that will indicate that it failed (e.g. -1 for open() , or NULL for fopen() , etc). You really should be testing the return value for failure before checking perror()
|
|
|
|
|
I have started doing both checks - return values and errno.
If I understand perror it does something special when errno is zero.
Perhaps I will try to keep track of errno.
There are two "weird" behaviour I am unable to grasp.
I am definitely getting different responses when running SAME code on X86 and ARM7.
I am working on that to make sure.
Even if errno is NOT changed between calls, getting "Invalid parameters" is puzzling when the parameters are SAME in both calls.
Here is a proof you are on the right track !
Code
socket_fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
#ifdef TRACE
cout << "Socket errno " << dec << errno << " @line " << __LINE__ << endl;
perror("STATUS allocate socket ");
this call sets the errno to 22 - AFTER perror is executed with errno being set to 0 success!
cout << "socket_fd " << dec << socket_fd << endl;
this call
cout << "Socket errno " << dec << errno << " @line " << __LINE__ << endl;
#endif
here the errno is still set to 22 !
socket_fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
#ifdef TRACE
cout << "Socket errno " << dec << errno << " @line " << __LINE__ << endl;
perror("STATUS allocate socket ");
cout << "socket_fd " << dec << socket_fd << endl;
cout << "Socket errno " << dec << errno << " @line " << __LINE__ << endl;
exit(-1);
#endif
Output
SERVER_X86_228
RPI_ARM
date version Feb 29 2020
test time 13:37:53
STATUS allocate socket : Success
BREAK @line 47
Socket errno 0 @line 61
socket_fd 3
Socket errno 22 @line 64
Socket errno 22 @line 72
socket_fd 4
Socket errno 22 @line 75
STATUS allocate socket : Invalid argument
modified 29-Feb-20 14:47pm.
|
|
|
|
|
Good point, I totally forgot about that.
|
|
|
|
|
perror(3) - Linux manual page[^]
Add a direct quote from man
When a system call fails, it usually returns -1 and sets the variable
errno to a value describing what went wrong. (These values can be
found in <errno.h>.) Many library functions do likewise. The
function perror() serves to translate this error code into human-
readable form. Note that errno is undefined after a successful
system call or library function call: this call may well change this
variable, even though it succeeds, for example because it internally
used some other library function that failed. Thus, if a failing
call is not immediately followed by a call to perror(), the value of
errno should be saved.
And I am not the only one using perror wrong. Take this gem
I have commented out here just to show the original code.
This "example" shows why some coders do not check the call result.
errcode = getaddrinfo("z_desktop", NULL, &hints, &res);
if (errcode != 0) { perror("STATE getaddrinfo");
return -1;
}
|
|
|
|
|
I have moved the code to run on RPi ARM and have NO ISSUES!
I shall go ahead and finish my experiment passing data using bluetooth on SAME hardware,
Perhaps when I get it fully working it will be easier to find why it fails on X86.
Thanks four your help.
|
|
|
|
|
how do you run a console program with arguments on windows 7? when you run it from the shell the window disapears instantly.
|
|
|
|
|
|
|
Run it in a cmd window, just like in a Linux terminal.
|
|
|
|
|
notice taken, thank you Richard
|
|
|
|
|
use
cmd /k yourapp - the /k prevents the window from closing once the app has finished running.
|
|
|
|
|
I`m learning assembler. I need advice for picking a compiler.
|
|
|
|
|