Issue with LVGL Graphics Library on Pros for v5 3.1.6

I’'m designing a GUI for my team’s robot this year, and I’m trying to implement a keyboard with the command:

lv_obj_t *kb = lv_kb_create(lv_scr_act(), NULL);

I don’t get any errors in the diagnostic pane, but for whatever reason when I compile it says something about an undefined reference to lv_kb_create(). Yes, I have already checked to make sure the USE_LV_KB macro was enabled in lv_conf.h, and I’m including the correct header files.

Any ideas?

Team 64 “Double Down”

Check include/display/lv_conf.h, line 295 or so:

/*Keyboard (dependencies: lv_btnm)*/
#define USE_LV_KB 0

It means the LVGL inside PROS was compiled w/o keyboard support. Changing that define won’t help you, since LVGL is shipped precompiled (inside firmware/libpros.a)
If you really need to, you can likely implement such a keyboard yourself though.


Someone also recently asked about this on GitHub, and we might get it in the next release of pros.

1 Like

I read the open source code of pros team. It seems that it’s no trouble to separate lvgl. Maybe I don’t know the deeper problem.

LVGL keyboard has been enabled in latest version of PROS.


The problem is that it would need access to some things that we don’t expose in the public-facing API. Once we deal with that, there are also some more structural concerns about when and how we should run initialization code that need to be addressed still.


I can’t help you on GitHub because of language and technical problems. I have started to work on Pros sim in a comprehensive way. At present, lvgl is an independent static library

@hotel if you’re looking into initialization code overhaul, I’d have a HUGE wish: Make main() the actual code entry point and let the user control the initialization. I’ll try to explain:

When working on MCUs, deep embedded or even reasonably embedded but high-reliability control systems, I as a rule avoid dynamic allocation (at least wherever possible). Think of a hard-to-service system that has to have uptime in years - what would happen to your heap fragmentation, for example.

For a typical system with many interdependent subsystems, I “allocate” all those subsystems on the stack of the main() function and enter whatever control loop (RTOS, some event queue or a simple round-robin scheduler) from there. That way, I always have all the systems properly allocated, cross referenced, possibly freed in the correct order (under testing or if that system has a concept of shutdown). Something like this (made up sample that would apply to robot use case):

int main(...) {
    Motor left(...);
    Motor right(...);
    Gyro gyro(...);
    Chassis chassis(left, right, gyro); // passing in references
    Robot r(chassis, ....);


    SystemStateDispatcher mainDispatch(teleop, autons, ....);


I think that approach like this is doable in VexCode, since you own main() and it has the vex::competition class that allows you registering callbacks for auton and teleop (instead of providing fixed symbol callbacks, though I’d rather see a class with virtual members you’d subclass, allows you to keep any context you want to pass).
As for initializing whatever you need, you might request a PROS object to be declared first (and LVGL integration too), such as:

int main(...) {
    PROS pros; 
    LVGL lvgl;

That way, you have full control over initialization order, no globals to worry about and so on.

Under current PROS setup, I’d have to allocate objects on the heap in initialize and keep a global pointer, or just go flat global with all the objects (and all the problems it brings).


I hear what you’re saying, but I’m going to have to disappoint you slightly here.

First off, I want to explain that the reason we set things up in the way we did was primarily to mimic the style of code users coming from the cortex to the V5 would be familiar with. A secondary point is the UX-- three years ago when we began development of PROS 3, we felt (and still do feel to some extent) that requesting the user to have a hand in low-level initialization tasks is going a bit too far (consider also the stigma around using PROS at the time).

Second of all, at this stage of the game I do not think it would be wise to refactor the initialization in a way that impacts existing user code. Indeed, the current plan for initialization order will be invisible to most users. Said plan is (as of right now) to split PROS kernel initialization into three or so distinct phases using the constructor attribute and a few predefined priorities. This way, you’ll be able to (sort of) hook into this initialization process, and make sure things are initialized at the right times. It’s not the most elegant solution to be sure, but it is the lowest impact thing I can think of that will solve the problems I have with the current setup.

Now for some more specific responses:

I agree that allowing users to register their own callbacks would have been preferable, and I’ll see if there’s a way we might be able to implement this in a low-impact way (though I suspect this is non-trivial). This was partly an oversight in the design process, and partly intentional for the reasons above wrt keeping the code familiar.

I agree here, too. That said, PROS is by design a C-first API despite appearances to the contrary. This is mostly because at the time we were all vastly more familiar with C than with C++, which is also the reason that our C++ API is mostly just a very thin wrapper around the C one.


I understand the reservations here, and again agree with them. However, I’d like to point out that in this case you can use C++'s smart pointers instead of raw ones, which mitigates the need for manually managing the memory (i.e. with malloc/free or new/delete). Also I’d argue that heap fragmentation is not really an issue in this context given that a) the total heap size is about 48MB and b) the max runtime for the majority of programs is capped at two minutes.

It may be a bit too late for PROS 3 at this point, but it’s my sincere hope that whoever ends up in charge of PROS 4 will keep your points in mind.