Closed joerossrobotics closed 1 year ago
I am not aware of any ready-made examples for this (perhaps try GitHub code search, maybe someone has already made one), but I imagine it to be a straightforward task. If you need any advanced support with this including writing code, please reach out to sales@zubax.com. Thanks!
Hi,
In terms of implementing the ICANDriver class, are the push / pop / etc functions supposed to work with the libcanard queue, or directly with the MCP2515? I'm slightly confused as to whether the user is supposed to work with cyphal directly, or if this is handled internally by kocherga.
Thanks for the quick reply :)
Cyphal is handled by Kocherga entirely, so the user works with raw CAN frames. That is to say, with MCP2515.
One final question,
In terms of implementing IROMBackend, the RP2040 is only able to erase sectors of 4096 bytes, and write pages of 256 bytes. In terms of erasing the flash, does Kocherga make the image_size variable of the AppDescriptor struct available to the user prior to beginning writing the data (one option is to erase this to the closet multiple of the sector size in the beginWrite() method). The other option is to erase the data dynamically by tracking the amount of data written with a static variable and erasing another sector of flash as needed in the write() method.
I'm aware that the firmware is written progressively using write() until the upload is finished. Is there internal provision to tell Kocherga to write the data in multiples of the page size? The best solution I suppose would be to tell Kocherga to write the application to flash in multiples of the sector size, and erase the sector about to be written every time write() is called.
Thanks again for all your help! :)
The other option is to erase the data dynamically by tracking the amount of data written with a static variable and erasing another sector of flash as needed in the write() method.
This is the recommended approach (sans the static variable, you don't need this).
I'm aware that the firmware is written progressively using write() until the upload is finished. Is there internal provision to tell Kocherga to write the data in multiples of the page size?
No, you should implement buffering in your IROMBackend implementation.
The best solution I suppose would be to tell Kocherga to write the application to flash in multiples of the sector size
This would require Kocherga to implement buffering internally and thus do the job of your IROMBackend.
I see, so something along these lines:
class MyROMBackend final : public kocherga::IROMBackend
{
public:
std::optional<std::size_t> write(const std::size_t offset, const std::byte *const data, const std::size_t size) override
{
// Add Data To Buffer
writeBuffer.insert(writeBuffer.end(), data, data + size);
// If There Is At Least One Sector To Write
while (writeBuffer.size() >= FLASH_SECTOR_SIZE)
{
// Erase Sector
flash_range_erase(currentOffset, FLASH_SECTOR_SIZE);
// Write Sector To Flash
uint8_t tempBuffer[FLASH_SECTOR_SIZE];
memcpy(tempBuffer, data, FLASH_SECTOR_SIZE);
flash_range_program(currentOffset, tempBuffer, FLASH_SECTOR_SIZE);
// Remove Written Data From Buffer
writeBuffer.erase(writeBuffer.begin(), writeBuffer.begin() + FLASH_SECTOR_SIZE);
// Increment Current Sector Offset
currentOffset += FLASH_SECTOR_SIZE;
}
return size;
}
void endWrite() override
{
// Pad Final Secttor With Zeros
while (writeBuffer.size() < FLASH_SECTOR_SIZE)
writeBuffer.emplace_back(0);
// Write Final Sector To Flash
uint8_t tempBuffer[FLASH_SECTOR_SIZE];
memcpy(tempBuffer, &writeBuffer, FLASH_SECTOR_SIZE);
flash_range_program(currentOffset, tempBuffer, FLASH_SECTOR_SIZE);
}
std::size_t read(const std::size_t offset, std::byte *const out_data, const std::size_t size) const override
{
memcpy(out_data, reinterpret_cast<uint8_t *>(offset), size);
return size;
}
private:
size_t currentOffset = 0;
std::deque<std::byte> writeBuffer;
};
Perhaps. The memcpy you invoke at the end is ill-formed and you don't really need a deque here, a regular std::array would do; otherwise it's close.
@joerossrobotics I'm currently working on getting Kocherga working on rp2040 with can2040 for the can driver and CMake for build. Some components will obviously be different, but I am happy to work with you/help test the stuff that could be the same between our use cases--probably linker scripts, IROMDriver, and generic pico sdk calls.
Hi,
I was wondering if there exists any examples of using this project that would help me integrate it with an RP2040 & MCP2515 CAN Controller. I'm familiar with using libcanard and the 107 MCP2515 library to produce cyphal nodes. I've also written the code to boot a user program from flash on the RP2040 - the main issue is implementing classes such as:
Any help would be greatly appreciated.