CanardRxTransfer payload reading?

However the “transport layer” term exist nowhere else in this file and I cannot find this section.
What exactly is the “descriptor” referring to? message id?

The text refers to the specification (that’s v1 but it is identical with v0 in this regard). The specification has a section titled “4.1.5. Transfer descriptor”, where it says this:

Transfer emission and reception processes rely on the concept of transfer descriptor.
A transfer descriptor is a set of properties that identify a particular set of transfers that originate from the same source node, share the same port-ID, same kind (message or service), and are addressed to the same destination node (the latter applies only to unicast transfers).


The reason I ask is because terminology in the description does not appear to match the code.
It is unclear, could you please clarify?

We should work more on the documentation. The terminology you are looking for is defined well by Specification; I agree that the format is not very user-friendly but it’s the only source we have at the moment. We would certainly welcome contributions improving our docs!

Could you please clarify this in a simple way.
i.e. like every message id type should have it’s own static variable.

If you want to publish a message, you need one transfer-ID variable per data type ID (or subject-ID if you’re using the stable UAVCAN v1.0 instead of the experimental v0).

If you want to call a service, you need one transfer-ID variable per ((data type ID or service-ID if you’re using v1) AND server node-ID).

If you want to respond to a service, you don’t need any transfer-ID variables; instead, you re-use the transfer-ID value you got in the request.

Hi,
Thanks, I implemented a unique id for each data type ID and it seems to work ok now at least for the not normal case (i.e… not bridged), for forwarding bridged messages I allocataed a pool and use one for each node and data type id combo. Haven’t tested this yet but should be ok frfom what you say. For responses I’m still using a unique one, even though not strictly necessary, but can’t hurt as the unique transfer ID variable is set to the one passed in first anyway.
I’ll test the bridge later but all good for now, thanks!

Back to the other Q, is there a sample code (with main function) for implementing uavcan protocol on kocherga? I haven’t done much c++ and it was a long time ago, so a sample here would be good to get started. I couldn’t find a description of the test files in the test folder, and I can’t seem to find one here that does that.
Are there any pointers for getting started with kocherga with uavcan?
Thanks.

I would advise studying the specification carefully before departing from it as you described lest you end up with a broken protocol. The problem with your change is that it is necessary to re-use the same transfer-ID in the response transfer to let the client match the request with the response; the modified behavior will break service calls. Please, please follow the documentation unless you have an in-depth understanding of the motivation behind every requirement provided in the specification.

Sure. Here:

Hi, Thanks,
silly question, but I found no reference to kocherga in there whatsoever.
A search for that term in the bootloader folder returns no results.
Is this using kocherga or did you misread the question?

Thanks

Hi,
I tried to build the zubax gnns firmware but got theses errors:
Compiler failure
Traceback (most recent call last):
File “libuavcan/libuavcan/dsdl_compiler/libuavcan_dsdlc”, line 61, in
dsdlc_run(args.source_dir, args.incdir, args.outdir)
File “/mnt/c/users/kentm/documents/github/sw4stmworkspace/zubax_gnss/firmware/libuavcan/libuavcan/dsdl_compiler/libuavcan_dsdl_compiler/init.py”, line 62, in run
run_generator(types, output_dir)
File “/mnt/c/users/kentm/documents/github/sw4stmworkspace/zubax_gnss/firmware/libuavcan/libuavcan/dsdl_compiler/libuavcan_dsdl_compiler/init.py”, line 111, in run_generator
die(ex)
File “/mnt/c/users/kentm/documents/github/sw4stmworkspace/zubax_gnss/firmware/libuavcan/libuavcan/dsdl_compiler/libuavcan_dsdl_compiler/init.py”, line 89, in die
raise DsdlCompilerException(str(text))
DsdlCompilerException: line 16, col 17: invalid syntax (, line 1)
line 16, col 17: invalid syntax (, line 1)

Compiling air_sensor.cpp
cc1plus: error: -Werror=implicit-fallthrough: no option -Wimplicit-fallthrough
cc1plus: error: -Werror=bool-operation: no option -Wbool-operation
zubax_chibios///chibios/os/common/ports/ARMCMx/compilers/GCC/rules.mk:198: recipe for target ‘build/obj/air_sensor.o’ failed
make: *** [build/obj/air_sensor.o] Error 1

I have python 3.6 and python 2.7 installed and running on ubuntu 18.04 under windows.

Sorry, the code I linked above is based on a much earlier library which was a prototype of Kocherga. Please use this example instead:

kocherga-demo.tar.gz (27.9 MB)

I had to edit the sources manually before publishing but they should still be valid.

You are running a very old GCC. The demo attached here requires v7.3.

Why the code generator has failed is unclear; consider re-running with -v if the issue persists.

Pavel,
I downloaded the link you sent.
It seems that this the korcherga repo test folder just with the libcanard and other libraries already in there.
I have seen this before as this was one of the first links you sent.
I had already looked at this and I was asking which of the files is the demo for korcherga with libcanard?
This is still my question, as I said earlier there is no explanation for what files in the test folders do.
Can you provide an explanation of what each test file does, or just the one I need to use korcherga with libcanard to make a bootloader. Please read the previous messages and provide more detail please as there is little to no documentation to explain any test code.
Thanks

The archive that I attached contains a demo application for Kocherga, which I understood you were looking for.

Yes, it’s in the archive:

Hi pavel,
thanks I gave it a try to build and it failed.
I am using GCC 7,4
gcc --version
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0

make RELEASE=1
gets error:
s/various -Ichibios/os/license -Isrc -Isrc/os -Ilibcanard -Ilibcanard/drivers/stm32 -Isenoval -Ipopcop/c++ -Ikocherga src/app_shared/app_shared.cpp -o build/obj/app_shared.o
cc1plus: error: -Werror=implicit-fallthrough: no option -Wimplicit-fallthrough
cc1plus: error: -Werror=register: no option -Wregister
cc1plus: error: unrecognized command line option ‘-Wno-register’ [-Werror]
cc1plus: error: unrecognized command line option ‘-Wno-implicit-fallthrough’ [-Werror]
cc1plus: all warnings being treated as errors
chibios/os/common/startup/ARMCMx/compilers/GCC/rules.mk:213: recipe for target ‘build/obj/app_shared.o’ failed
make: *** [build/obj/app_shared.o] Error 1

Thanks,
Kent

Hi,
Seem I have the wrong version of arm-eabi-none-g++ .
Had a lot of trouble but finally got the newer version of compiler on there and it is building, yay!
I’ll try getting it to work now if I can find how the rom is arranged.
Where is the bootoader usually located?
The smaller flash pages are at the beginning (in the f4) so is the boot loader usually at the end?

Thanks.

Hi,
Im trying to figure out how to use this code.
i.e. where is flash size defined?
I found flash offset, but can’t find where you are defining the processor in the code.
I am not sure if CAN is enabled in the sample you sent.
in halconf.h HAL_USE_CAN is defined false.
If I define it to true and define serial options to false it gets an error CAN driver activated but no CAN peripheral assigned.
Do I then need to define the CAN port in the mcuconf file similar to some of the mcuconf files similar to some of the stm32 demo versions under chibios?

Thanks

Hi,

Also How do I add another board?
Ia m using a f413 and it appears this type has not been used before.

Thanks

All ARM-based microcontrollers known to me boot from 0x00000000 so the bootloader is always at the very beginning.

It’s in the linker script named ld.ld located in the root directory. This is where the size of the bootloader itself is defined as well.

This is correct. The sample does not use the CAN driver supplied by the operating system (it’s defective); instead, it uses the driver shipped with Libcanard, which requires no support from the operating system.

The MCU abstractions are managed by ChibiOS, so you should refer to its documentation. Briefly, in the Makefile you will find this section:

# MCU-specific OS includes
include $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
include $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/platform.mk
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk

Update it if necessary. Then edit src/os/halconf.h and src/os/board.h.

Hi,
I have modified the files and checked PLLcfgr and cfgr registers and looks ok.
It computes the same timings my other code does but when it gets to canardSTM32Init it fails with error
CANARD_STM32_ERROR_MSR_INAK_NOT_CLEARED when attempting to leave init mode.
I changed optimization back to none to debug it.
Do you have any clues why this may be happening on the kocherga project?
I haven’t got the other hardware to test if this code is working correctly.
My other projects run fine on the same hardware.
Thanks.

This is rather typical for misconfigured or malfunctioning hardware. Before leaving the init mode, the CAN controller waits for 11 consecutive recessive bits to appear on the RX line. The most common reason for this process to time out is for the physical layer to be malfunctioning or for pin remapping to be configured incorrectly. You could re-check the remapping config and also you should sample the RX pin directly to see if it is at the recessive (high, logical 1) level.

Thanks,
will do
Kent

Pavel,
Thanks that solved the problem and got it running.
However now I can manage to program successfully but it will not execute my application correctly.
I then debugged my code with the bootloader still in place and then my code ran correctly.
The only difference in the binary will be the checksum will blank in the debugged code since that is added after building and only for the binary to be programmed in.
I noted that the image should be 8 bytes aligned in the notes , is that taken care of with the populate_app_descriptor script?
As soon as I debug everything works so I’m not sure what is going wrong.
Could it be the watchdog? or something else that is disabled when debugging.
i.e. my code doesn’t use a watchdog yet, so not sure if kocherga or chibios is leaving it on, or it is a clean boot into the application code.
Also once I have gotten this to work how do I get the bootloader to activate when the application is valid?

Thanks,
Kent

Ah yes, it happens. The most likely reason is that the bootloader launches the application incorrectly, e.g. by not disabling interrupts first, or by jumping to the wrong location, or maybe your application is linked incorrectly – check the *.ld file and make sure the bootloader’s space is factored in. When you launch the application using the debugger, it always initializes it from the well-known reset state, so it works.

The most relevant piece is here (under board/board.cpp in the demo I shared):

[[noreturn]]
void bootApplication()
{
    // Loading and validating the application entry point
    const unsigned stacktop   = *reinterpret_cast<unsigned*>(FLASH_BASE + APPLICATION_OFFSET);
    const unsigned entrypoint = *reinterpret_cast<unsigned*>(FLASH_BASE + APPLICATION_OFFSET + 4);


    if ((stacktop <= SRAM_BASE) ||
        (stacktop > (SRAM_BASE + 2 * 1024 * 1024)))
    {
        chibios_rt::System::halt("STACKTOP");
    }


    if ((entrypoint < (FLASH_BASE + APPLICATION_OFFSET)) ||
        (entrypoint >= (FLASH_BASE + getFlashSize())))
    {
        chibios_rt::System::halt("ENTRYPOINT");
    }


    // We cordially extend our thanks to David Sidrane and Ben Dyer, whose ideas have somewhat inspired this thing.
    asm volatile("cpsid i");


    // Deinit all peripherals that may have been used
    // It is crucial to disable ALL peripherals, else a spurious interrupt will crash the application
    RCC->APB1RSTR |=  (RCC_APB1RSTR_CAN1RST | RCC_APB1RSTR_CAN2RST | RCC_APB1RSTR_USART3RST);
    RCC->AHB2RSTR |=  RCC_AHB2RSTR_OTGFSRST;


    // Kill the sys tick
    SysTick->CTRL = 0;


    // Update the vector table location
    asm volatile("dsb");
    asm volatile("isb");
    SCB->VTOR = FLASH_BASE + APPLICATION_OFFSET;
    asm volatile("dsb");


    // Let's roll!
    asm volatile("msr msp, %[stacktop]          \n"
                 "bx       %[entrypoint]        \n"
                 :: [stacktop] "r"(stacktop), [entrypoint] "r"(entrypoint):);


    for (;;) { }        // Noreturn
}

The script will pad the binary automatically if needed. You only need to ensure that the ROM start address in the application’s linker script is aligned at 8 bytes.

Watchdog is not disabled while debugging.

Hi,
I’m just debuggin in to see what kocherga is actually doing.
I have set up my code to run at ofset 0x20000 from the flash base.
I have adjusted the parameters to load the vectors at the correct offset for this.
I have adjusted the parameters in kocherga to offset the code as well.
This is done in 2 places
ld.ld
flash : org = 0x08000000, len = 130816 /48896/
that is 0x20000 -256 to allow for marker section
makefile
APPLICATION_OFFSET = 131072 #49152
move from xc000 to x20000 ( i need more space for no optimization of bootloader for debugging)
However when I debug I find it sets
stacktop = 0x20050000
entrypoint = 0x80265DD
Where is the 65DD coming from?
In my code there is a marker in the binary but dies not exists as the first entry before the rest of the code but rather as a constant in the code relatively close to the start of the binary but not at 0 offset.
I don’t understand how FLASH_BASE + APPLICATION_OFFSET + 4 becomes 0x80265DD when it should be 0x8020004?
I think this is where the problem is, could yo elaborate why this is done and what expectations you have of the binary bearing in mind it is not built with your build system.

Thanks

Hi,
It seems you are also reading/writing to a section of ram at 0x2001ff00, can you explain what you are sharing between the two programs and why?
I was expecting there not to be a shared memory location and interactions to be handled using registers and not hard coded memory maps.

Thanks