Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUGFIX: Enable QPU when accessing Register Map #52

Open
wants to merge 19 commits into
base: development
Choose a base branch
from

Conversation

wimrijnders
Copy link
Contributor

Accessing the register map won't work if the VideoCore is not powered up. This PR adds code to detectPlatform() to ensure that VideoCore is enabled before reading the registers.

In addition:

  • Adjusted some code for better debugging. Notably, a call to perror has been
    added in MailBox.cpp.
  • Left in debug printf's where useful. These are commented out in general.
  • Added RegisterMap::enabled(), which checks if the VideoCore registers are accessible.

The latter is actually a useful method to determine if the VideoCore is running.

Accessing the register map won't work in the VideoCore is powered up.
This adds code to `detectPlatform` to ensure that VideoCore is enabled before
reading the registers.

In addition:

- Adjusted some code for better debugging. Notably, a call to `perror` has been
  added in `MailBox.cpp`.
- Left in debug printf's where useful. There are commented out in general.
- Added RegisterMap::enabled(), which checks if registers are accessible.

The latter is actually a useful method to determine if the VideoCore is running.
@mn416
Copy link
Owner

mn416 commented Jul 15, 2018

Hi @wimrijnders,

I my recent work I also had to disable compilation of RegisterMap.cpp due to the following error.

Compiling Lib/VideoCore/RegisterMap.cpp
In file included from /opt/vc/include/interface/vcos/vcos_assert.h:149:0,
                 from /opt/vc/include/interface/vcos/vcos.h:114,
                 from /opt/vc/include/interface/vmcs_host/vc_dispmanx.h:33,
                 from /opt/vc/include/bcm_host.h:46,
                 from Lib/VideoCore/RegisterMap.cpp:8:
/opt/vc/include/interface/vcos/vcos_types.h:38:33: fatal error: vcos_platform_types.h: No such file or directory
compilation terminated.
make: *** [obj-qpu/VideoCore/RegisterMap.o] Error 1

Of course I'm on an old version, but it would be nice if running make would still work on old platforms.

@wimrijnders
Copy link
Contributor Author

I agree it should work on old version, but nevertheless: crap.

I'll see whatever I can find on the vcos headers of old. Would you mind for now to send me a listing of /opt/vc/include/interface/vcos/?

I wish I could test this old stuff somehow. I should have an old Raspbian SD-card somewhere....

@wimrijnders
Copy link
Contributor Author

wimrijnders commented Jul 15, 2018

In file /opt/vc/include/interface/vcos/vcos_types.h:

#if defined(__unix__) && !defined(__ANDROID__)
#include "interface/vcos/pthreads/vcos_platform_types.h"
#else
#include "vcos_platform_types.h"
#endif

The first case is used for my system. I'm thinking that in your case, the first should be selected as well but isn't. So I think the best way is to force the #define's upon use.

Found an old Raspbian SD-card BTW. Now to see how to use it, if it's usable at all....
EDIT: It's a 'big' SD, the Pi 2 and 3 take only micro's. The Pi 1 is my backup server, hesitate to take it offline. Perhaps I can copy to micro....

@wimrijnders
Copy link
Contributor Author

Checked all places (3) in include where __unix__ is used within /opt/vc/include, I think we're safe. If anything, setting it will prevent more compilation errors.

@wimrijnders
Copy link
Contributor Author

@mn416 Added a fix for the usage of __linux__. See if this works for you.

In addition, a fix in detectPlatform for some issues I noticed:

  • Avoid the sudo-message when checking for enabled register map
  • Add timeout for accessing register map. Apparently, the VideoCore needs some initial time to start up

@wimrijnders
Copy link
Contributor Author

> obj-qpu/bin/detectPlatform 
Detected platform: Raspberry Pi 2 Model B Rev 1.1
Can't open device file: /dev/vcio
Try creating a device file with: sudo mknod /dev/vcio c 100 0

Well, crap again. This happens on Pi 2 but not on Pi 1. All is well if you run with sudo.

I can track it down to group permissions:

> ls -al  /dev/vcio
crw-rw---- 1 root video 249, 0 Jul  7 14:17 /dev/vcio

# Pi 1
> groups
wim sudo video

# Pi 2
> groups
wim sudo netdev

In other words, the user has to be a member of groupvideo.

It's frightening how things escalate...., doing my best to keep it in check.

@wimrijnders
Copy link
Contributor Author

wimrijnders commented Jul 15, 2018

This actually implies a way to avoid sudo; just become a member of the relevant group:

> sudo useradd -g video wim
> sudo useradd -g kmem wim

Logout, login and bob's your uncle. No more nag messages about sudo. I checked it, it works.
This is something for a 'Good to know' column in the docs.

@wimrijnders
Copy link
Contributor Author

@mn416 I take previous back about joining specific groups. It works for /dev/vcio but I can't get it to work for /dev/mem. Best to stick with sudo.

wimrijnders pushed a commit to wimrijnders/QPULib that referenced this pull request Jul 16, 2018
Now that DMA is enabled, it's interesting to know what the actual size is of the VPM.
This adds it to the output of `detectPlatform`.

Example output:

```
> sudo obj-qpu/bin/detectPlatform
Detected platform: Raspberry Pi 2 Model B Rev 1.1
Hardware revision: a01041
Number of slices: 3
Number of QPU's per slice: 4
Size of VPM: 12KB                    # <-- This is new

```

**NOTE:* This will probably not work on your machine until mn416#52 and mn416#53 have been merged.
@mn416
Copy link
Owner

mn416 commented Jul 16, 2018

Hi @wimrijnders,

Can you explain the following?

#if defined(LINUX_PREVIOUSLY_UNDEFINED)
#define __linux__
#undef LINUX_PREVIOUSLY_UNDEFINED
#endif

Just wondering, what is the purpose if #define __linux__ here?

@wimrijnders
Copy link
Contributor Author

wimrijnders commented Jul 16, 2018

See this comment. This is what appears in the location of the compile error.

The if-part of the include is the one that's required. It gets picked up OK on my Pi's but not on yours; so, one of the define's must be wrong in your case.

This is my assumption: __linux__ is not used by the compiler of your old distro. It's either that or the ANDROID define is active in some way. So my 'hack' is to define __linux__ before including the bcm headers, if it wasn't defined already.

Does this make sense?

Note that it gets cleaned up afterward again.


Edit: The question implies that I should put a comment there to explain it. It's not complicated, but the reason it's there is quite obscure.

@wimrijnders
Copy link
Contributor Author

wimrijnders commented Jul 16, 2018

OH CRAP! I see what you mean. It should be #undef. facepalm.
This is the cleanup part.

@wimrijnders
Copy link
Contributor Author

😊 There, fixed.

@wimrijnders
Copy link
Contributor Author

Have you considered using the review features in the 'Files changed' BTW?

Perhaps you're not aware that if you hover on a '+' before a code line, you get a clickable '+' icon which opens a comment block specific for that line. If you are aware of this, forgive my well-intended pedantry.

@mn416
Copy link
Owner

mn416 commented Jul 17, 2018

Hi @wimrijnders,

I gave this a try but I get the same error message as above.

Here is my "vcos" directory:

> ls /opt/vc/include/interface/vcos/
generic              vcos.h                  vcos_queue.h
pthreads             vcos_init.h             vcos_quickslow_mutex.h
user_nodefs.h        vcos_inttypes.h         vcos_reentrant_mutex.h
vcos_assert.h        vcos_isr.h              vcos_semaphore.h
vcos_atomic_flags.h  vcos_legacy_isr.h       vcos_stdbool.h
vcos_attr.h          vcos_logging_control.h  vcos_stdint.h
vcos_blockpool.h     vcos_logging.h          vcos_string.h
vcos_build_info.h    vcos_lowlevel_thread.h  vcos_thread_attr.h
vcos_cfg.h           vcos_mem.h              vcos_thread.h
vcos_cmd.h           vcos_mempool.h          vcos_timer.h
vcos_ctype.h         vcos_msgqueue.h         vcos_tls.h
vcos_dlfcn.h         vcos_mutex.h            vcos_types.h
vcos_event_flags.h   vcos_named_semaphore.h
vcos_event.h         vcos_once.h

I see that vcos_platform_types is here:

> ls /opt/vc/include/interface/vcos/pthreads/
vcos_futex_mutex.h  vcos_platform.h  vcos_platform_types.h

@wimrijnders
Copy link
Contributor Author

wimrijnders commented Jul 18, 2018

This is the same as my Pi's, in other words, as expected.

So, the assumption that in:

#if defined(__unix__) && !defined(__ANDROID__)
#include "interface/vcos/pthreads/vcos_platform_types.h"
#else
#include "vcos_platform_types.h"
#endif

... __unix__ is not defined is wrong. The problem must then be that __ANDROID__ is defined.
For some reason gcc thinks that you're compiling for an Android machine.

Will fix the #ifdef bit to handle __ANDROID__ instead. f that doesn't work, I'm out of ideas.

@wimrijnders
Copy link
Contributor Author

Aargh! I'm an idiot. I was #undef-ing __linux__ when it should be __unix__. Try again.

Actually, I'm going to force both.

@wimrijnders
Copy link
Contributor Author

OK done. Also a minor dependency fix in the Makefile. Try again?

Tell me if you see these while compiling:

#pragma message "__unix__ is NOT defined"

and/or

#pragma message "__ANDROID__ is defined"

I can remove the #pragma message statements aftwards.

@mn416
Copy link
Owner

mn416 commented Jul 22, 2018

Yes, was building from a clean state. If I set OLD_PI=yes then I get

In file included from Lib/VideoCore/RegisterMap.cpp:3:0:
Lib/VideoCore/RegisterMap.h:34:21: error: function definition does not declare parameters
Lib/VideoCore/RegisterMap.h:35:11: error: function definition does not declare parameters
Lib/VideoCore/RegisterMap.cpp: In constructor ‘QPULib::RegisterMap::RegisterMap()’:
Lib/VideoCore/RegisterMap.cpp:75:2: error: ‘m_size’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp:80:2: error: ‘m_addr’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp: In destructor ‘QPULib::RegisterMap::~RegisterMap()’:
Lib/VideoCore/RegisterMap.cpp:87:20: error: ‘m_addr’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp:87:28: error: ‘m_size’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp: In member function ‘uint32_t QPULib::RegisterMap::read(int) const’:
Lib/VideoCore/RegisterMap.cpp:103:9: error: ‘m_addr’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp: In static member function ‘static void QPULib::RegisterMap::check_page_align(unsigned int)’:
Lib/VideoCore/RegisterMap.cpp:179:52: error: ‘errno’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp:180:10: error: ‘exit’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp:185:10: error: ‘exit’ was not declared in this scope
Makefile:183: recipe for target 'obj-qpu/VideoCore/RegisterMap.o' failed
make: *** [obj-qpu/VideoCore/RegisterMap.o] Error 1

@wimrijnders
Copy link
Contributor Author

Huh? that's a strange error. The function doesn't declare parameters because there aren't any.

Compiles perfectly in my case.

@wimrijnders
Copy link
Contributor Author

wimrijnders commented Jul 22, 2018

It's not even a function:

  volatile uint32_t *m_addr{nullptr};

And there's no way the OLD_PI setting can influence this, since it's only used in the cpp, not the include file.

The only thing I can think of is that the c++ version setting c++0x of your compiler can't deal with nullptr. Far-fetched, I know. Perhaps it's time to upgrade it to c++11, the other one is a transient gcc-specific thing anyway.


EDIT: The initialization with {} might be the thing. It would make somewhat sense given the error message. The fix for that is to old-style initialization lists in the constructor. Or you upgrade your distro.

@wimrijnders
Copy link
Contributor Author

Replaced inline init with constructor initialization list.

This is to determine what the problem is. I still would prefer to use -std=c++11.

@mn416 mn416 mentioned this pull request Jul 23, 2018
@mn416
Copy link
Owner

mn416 commented Jul 23, 2018

Still seeing compile errors:

Compiling Lib/VideoCore/RegisterMap.cpp
In file included from Lib/VideoCore/RegisterMap.cpp:3:0:
Lib/VideoCore/RegisterMap.h:35:11: error: function definition does not declare parameters
Lib/VideoCore/RegisterMap.cpp: In constructor ‘QPULib::RegisterMap::RegisterMap()’:
Lib/VideoCore/RegisterMap.cpp:75:2: error: ‘m_size’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp: In destructor ‘QPULib::RegisterMap::~RegisterMap()’:
Lib/VideoCore/RegisterMap.cpp:87:28: error: ‘m_size’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp: In static member function ‘static void QPULib::RegisterMap::check_page_align(unsigned int)’:
Lib/VideoCore/RegisterMap.cpp:179:52: error: ‘errno’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp:180:10: error: ‘exit’ was not declared in this scope
Lib/VideoCore/RegisterMap.cpp:185:10: error: ‘exit’ was not declared in this scope
Makefile:190: recipe for target 'obj-qpu/VideoCore/RegisterMap.o' failed
make: *** [obj-qpu/VideoCore/RegisterMap.o] Error 1

@wimrijnders
Copy link
Contributor Author

wimrijnders commented Jul 23, 2018

Ah right, same problem, different variable. Hold on.

This is a compiler issue I believe; it can't handle the full c++11 syntax.

@wimrijnders
Copy link
Contributor Author

wimrijnders commented Jul 23, 2018

'Fixed' in last commit, please test. I'm running unit tests in the meantime.

EDIT: Unit tests passed.

@mn416
Copy link
Owner

mn416 commented Jul 23, 2018

Looks like you're just missing #include for stdlib.h and errno.h. If I add those, it compiles.

Compiling Lib/VideoCore/RegisterMap.cpp
Lib/VideoCore/RegisterMap.cpp: In static member function ‘static void
QPULib::RegisterMap::check_page_align(unsigned int)’:
Lib/VideoCore/RegisterMap.cpp:179:52: error: ‘errno’ was not declared
in this scope
Lib/VideoCore/RegisterMap.cpp:180:10: error: ‘exit’ was not declared
in this scope
Lib/VideoCore/RegisterMap.cpp:185:10: error: ‘exit’ was not declared
in this scope
Makefile:190: recipe for target 'obj-qpu/VideoCore/RegisterMap.o'
failed
make: *** [obj-qpu/VideoCore/RegisterMap.o] Error 1

@wimrijnders
Copy link
Contributor Author

Thanks for reporting.

I've just been racking my brains to figure out why it compiles fine without those on my machines. I can't find a reason and will leave it at that. Just one of those things.

Did you manage to run sudo obj/qpu/bin/detectPlatform after make DEBUG=1 detectPlatform? That would be an indication that the register map is working as expected.

@wimrijnders
Copy link
Contributor Author

Also, important, I want to know if you also compile on a Pi 1. Because you mentioned somewhere that you switched to Pi 2 for faster compilation.

This is important for the bcm peripheral address, which is different on the Pi 1.

@mn416
Copy link
Owner

mn416 commented Jul 23, 2018

Did you manage to run sudo obj/qpu/bin/detectPlatform

Works on Pi 2

@mn416
Copy link
Owner

mn416 commented Jul 23, 2018

Builds and runs on Pi 1, but takes a few seconds to complete and gives unexpected output:

Hardware revision: 000d
Number of slices: 15
QPUs per slice: 15

@wimrijnders
Copy link
Contributor Author

Yes, because the peripheral address is different like I mentioned. But thanks for checking anyway.
Will fix it tomorrow - I actually took a shortcut in the code because I thought you were running Pi 2 only. Oh well.

@wimrijnders
Copy link
Contributor Author

Great that you mentioned the hardware revision as well. Useful.

@wimrijnders
Copy link
Contributor Author

Last commit adds explicit detection of Pi model using hardware revision for determining the peripheral address. This should now also work on your Pi 1.

In addition I added some descriptive commenting, also in the Makefile.

@wimrijnders
Copy link
Contributor Author

@mn416 Would you mind testing the following?

  • Test the platform detection, enable the following line in Makefile:
# Enable following
USE_BCM_HEADERS:= $(shell grep bcm_host_get_peripheral_address /opt/vc/include/bcm_host.h && echo "no" || echo "yes")
# Disable: USE_BCM_HEADERS:=no
  • Compile for c++11. In Makefile:
CXX_FLAGS = -Wconversion -std=c++11 -I $(ROOT) -MMD -MP -MF"$(@:%.o=%.d)" -g  # Add debug info: -g
#                             ^^^^^   Change to this

Do these work as expected now on your Pi's?

@mn416
Copy link
Owner

mn416 commented Jul 24, 2018

Need to include stdio.h. Then builds on a Pi 1 but when running:

This is a Pi platform
Hardware revision: 000d
Can't open device file: /dev/vcio

The device file exists.

@mn416
Copy link
Owner

mn416 commented Jul 24, 2018

c++11 not available on my Pi 1.

@mn416
Copy link
Owner

mn416 commented Jul 24, 2018

Doesn't build on Pi 1 if I use the following

USE_BCM_HEADERS:= $(shell grep bcm_host_get_peripheral_address /opt/vc/include/bcm_host.h && echo "no" || echo "yes")

@wimrijnders
Copy link
Contributor Author

wimrijnders commented Jul 24, 2018

OK. Silly thing is I removed it previous commit.

c++11 not available on my Pi 1.

OK, thanks for checking. So the baseline is c++0x. The frustrating thing is that the c++0x of my gcc version is different from yours.

Doesn't build on Pi 1 if I use the following

Thanks for checking. OK, I'll leave USE_BCM_HEADER:=no as default then. The comments covers the use of the variable for newer platforms.

@wimrijnders
Copy link
Contributor Author

wimrijnders commented Jul 24, 2018

These differences between platforms and compilers make a case for using makefile generation tools such as CMake or configure.

Not anything I would implement right now, but it's a thing to think about.

@wimrijnders
Copy link
Contributor Author

Actually, you don't need to generate the whole makefile, just a file that can be included with platform-specific settings, which could be generated with e.g. make configure.

Cutting this line of thought now, have other things to do.

@wimrijnders
Copy link
Contributor Author

@mn416 Will be leaving for 20 days vacation tomorrow. I would love to see this PR get merged before leaving, is it possible? Otherwise, no harm done.

If this gets accepted, it opens up a whole slew of functionality. Looking forward to that (for when I get back).

@mn416
Copy link
Owner

mn416 commented Jul 27, 2018

Only outstanding issue is that detectPlatform seems to fail on a Pi 1:

> sudo ./obj-qpu/bin/detectPlatform 
This is a Pi platform
Hardware revision: 000d
Can't open device file: /dev/vcio
Try creating a device file with: sudo mknod /dev/vcio c 100 0

As I said before, the device file exists. Is this behaviour expected?

@wimrijnders
Copy link
Contributor Author

No, not expected, this should just work. Will look at it when I return from vacation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants