Skip to content

Conversation

@ayoopierre
Copy link

Description

Motivation and Context

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Chore (refactoring, style fixes, git/CI config, submodule management, no code logic changes)

How Has This Been Tested?

  • Already covered by automatic testing.
  • New test added: (add PR link here).
  • Tested by hand on: (list targets here).

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing linter checks and tests passed.
  • My changes generate no new compilation warnings for any of the targets.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @ayoopierre, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new GRCANFD (CAN with Flexible Data-Rate) driver for the GRLIB CAN controller. It provides the necessary components to interact with the hardware, including a core driver, a user-space interface library, and a test application. This integration is a foundational step for future developments, specifically for LibCSP.

Highlights

  • New GRCANFD Driver Core: Implemented the grlib-can-core static library, providing low-level hardware interaction, interrupt handling, circular buffer management for TX/RX, and functions for device configuration and baud rate calculation.
  • GRCANFD Driver Binary: Introduced the grlib-can-driver binary, which acts as the main driver application, handling message-based communication from user-space applications to control the CAN hardware.
  • User-Space Interface Library: Added grlib-can-if, a static library that provides a simplified API for user applications to open, close, configure, send, and receive CAN messages from the driver.
  • CAN Test Application: Included can-test-app, a simple binary demonstrating the usage of the grlib-can-if library to interact with the GRCANFD device, performing basic send/receive and configuration operations.
  • Build System Integration: Updated _targets/Makefile.riscv64-noelv to include the new grlib-can-driver and can-test-app components, and added a dedicated Makefile for building all GRCANFD-related components.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@ayoopierre ayoopierre self-assigned this Jul 21, 2025
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new GRCANFD driver, including the core logic, a driver binary, an interface library, and a test application. The implementation is comprehensive but has several critical and high-severity issues related to correctness, resource management, and robustness. These issues should be addressed to ensure the driver is reliable.

return 0;
case can_reset:
grlibCan_resetDevice(device);
msg->o.err = EOK;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This case statement is missing a break. This will cause execution to fall through to the can_writeSync case, which is incorrect behavior.

Suggested change
msg->o.err = EOK;
msg->o.err = EOK;
break;

Comment on lines +203 to +208
grlibCan_cleanupResources(driverInstance.devices);
portDestroy(driverInstance.port);
grlibCan_unregisterDevices(&oid, driverInstance.devices, driverInstance.num);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This block of code is unreachable because grlibCan_messageThread has an infinite loop and will never return. This is a significant issue because the cleanup logic will never be executed, potentially leading to resource leaks. If the driver is intended to run forever, this cleanup code should be removed. If shutdown is a possibility, it must be handled correctly (e.g., via signal handlers), and the cleanup logic must be fixed.

device->ctrlReg = (1 << 1);

/* Sleeping until reset finished */
while ((device->ctrlReg & (1u << 1)) != 0) { }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This busy-wait loop polls a hardware register, which will consume 100% of a CPU core and can starve other threads. Consider adding a timeout and a sleep mechanism to make the driver more robust and efficient.


/* Configure ids to listen to */
device->confReg = 0;
device->confReg |= (1 << 2) | (1 << 1) | (1 << 1) | (1 << 6);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The flag (1 << 1) is duplicated in this bitwise-OR operation. This is likely a typo and could lead to incorrect device configuration. Please review the intended flags.

	device->confReg |= (1 << 2) | (1 << 1) | (1 << 6);

dev->rxBufAdd = mmap(NULL, _PAGE_SIZE,
PROT_WRITE | PROT_READ, MAP_UNCACHED | MAP_ANONYMOUS, -1, 0);
if (dev->rxBufAdd == MAP_FAILED) {
(void)munmap((void *)dev->txBufAdd, sizeof(grlibCan_msg_t) * dev->txBufSz);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The size passed to munmap is incorrect. mmap was used to allocate _PAGE_SIZE bytes. Therefore, _PAGE_SIZE bytes should be unmapped. Using sizeof(grlibCan_msg_t) * dev->txBufSz will likely unmap less memory than was allocated, causing a memory leak.

		(void)munmap((void *)dev->txBufAdd, _PAGE_SIZE);

}

if (dev->rxBufAdd != MAP_FAILED) {
(void)munmap((void *)dev->rxBufAdd, sizeof(grlibCan_msg_t) * dev->rxBufSz);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The size passed to munmap is incorrect. The rxBufAdd buffer was allocated with a size of _PAGE_SIZE. Therefore, _PAGE_SIZE bytes should be unmapped to avoid a memory leak.

		(void)munmap((void *)dev->rxBufAdd, _PAGE_SIZE);

Comment on lines 58 to 62
if (msg->i.size < sizeof(uint32_t)) {
msg->o.err = -1;
return -1;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The size check for can_getStatus is incorrect. It checks msg->i.size, but this operation writes to an output buffer and takes no input data. The check should be on msg->o.size to ensure the output buffer provided by the caller is large enough to hold the status.

Suggested change
if (msg->i.size < sizeof(uint32_t)) {
msg->o.err = -1;
return -1;
}
case can_getStatus:
if (msg->o.size < sizeof(uint32_t)) {
msg->o.err = -EINVAL;
return -1;
}

NAME := grlib-can-driver
LOCAL_SRCS := grlib-can-driver.c
DEP_LIBS := grlib-can-core
LOCAL_CFLAGS = -Wno-error

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using -Wno-error is discouraged as it can hide potential issues by preventing warnings from being treated as errors. It's better to fix the underlying warnings to improve code quality. If this is a temporary measure for development, a comment explaining the reason would be helpful.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, PR isn't draft, so this should be removed.

Comment on lines 26 to 29
while (lookup(canDevice, NULL, &canDev) < 0) {
printf("Device does not exist\n");
return EXIT_FAILURE;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This while loop is logically equivalent to an if statement. If lookup() fails, the program exits; otherwise, it continues. Using an if statement would represent the code's intent more clearly. If the goal is to wait for the device, the loop should include a sleep mechanism to avoid busy-waiting and high CPU usage.

Suggested change
while (lookup(canDevice, NULL, &canDev) < 0) {
printf("Device does not exist\n");
return EXIT_FAILURE;
}
if (lookup(canDevice, NULL, &canDev) < 0) {
printf("Device does not exist\n");
return EXIT_FAILURE;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's ok as is.


printf("Successfully checked CAN device oid\n");

printf("Can device open: %d\n", grlibCan_open(canDev));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The return value of grlibCan_open() is printed but not checked for errors. If the device fails to open, the program continues, and subsequent calls will likely fail. It's important to add error handling here.

@@ -0,0 +1,76 @@
#include <errno.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing file header

LOCAL_SRCS := can-test-app.c
DEP_LIBS := grlib-can-if
LOCAL_CFLAGS = -Wno-error
include $(binary.mk) No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No new line at the end of the file

NAME := grlib-can-driver
LOCAL_SRCS := grlib-can-driver.c
DEP_LIBS := grlib-can-core
LOCAL_CFLAGS = -Wno-error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, PR isn't draft, so this should be removed.

Comment on lines 26 to 29
while (lookup(canDevice, NULL, &canDev) < 0) {
printf("Device does not exist\n");
return EXIT_FAILURE;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's ok as is.

{
grlibCan_dev_t *dev = (grlibCan_dev_t *)arg;
volatile grlibCan_hwDev_t *device = dev->device;
volatile uint32_t pending = device->penIsr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This volatile does nothing - device->penIsr is volatile, local copy on stack is not.

Comment on lines 602 to 611
msg.type = mtCreate;
msg.oid = dir;
msg.i.create.type = otDev;
msg.i.create.mode = 0;
msg.i.create.dev.port = oid->port; /* Port number assigned by portCreate */
msg.i.create.dev.id = i; /* Id assigned by the driver itself */
msg.i.data = buf; /* Filename */
msg.i.size = strlen(msg.i.data);
msg.o.data = NULL;
msg.o.size = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use createdev()

Comment on lines +629 to +618
while (lookup("/dev", NULL, &dir) < 0) {
usleep(100000);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way for /dev on be present at this point?

}
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps some handling of abnormally big diff?


/* Core driver functions */
/* Create devices */
int grlibCan_initDevices(grlibCan_dev_t *dev, int num);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep two empty lines

}
msg->o.err = 0;
*(uint32_t *)(msg->o.data) = device->device->statReg;
msg->o.size = sizeof(uint32_t);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Server cannot modify these fields, it will be ignored.

@ayoopierre ayoopierre force-pushed the ayopierre/grlib-can branch 2 times, most recently from 8f0c524 to 55f1456 Compare July 21, 2025 13:57
#include <sys/mman.h>
#include <posix/utils.h>

/* Platform specific incldues */

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[codespell] reported by reviewdog 🐶
incldues ==> includes


uint32_t nomBdRate; /* Nominal baud-rate */
uint32_t dataBdRate; /* Data transfer baud-rate */
uint32_t transDelComp; /* Tranmission delay compensation */

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[codespell] reported by reviewdog 🐶
Tranmission ==> Transmission

@ayoopierre ayoopierre force-pushed the ayopierre/grlib-can branch from 55f1456 to 365435a Compare July 21, 2025 13:58
@github-actions
Copy link

github-actions bot commented Jul 21, 2025

Unit Test Results

7 918 tests   - 283   7 393 ✅  - 284   41m 52s ⏱️ - 1m 52s
  479 suites ±  0     515 💤  -   9 
    1 files   ±  0      10 ❌ + 10 

For more details on these failures, see this check.

Results for commit b030c67. ± Comparison against base commit 10baaaf.

This pull request removes 291 and adds 8 tests. Note that renamed tests count towards both.
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit.ioctl.data_in
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit.ioctl.data_in_big
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit.ioctl.data_inout
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit.ioctl.data_inout_big
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit.ioctl.data_out
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit.ioctl.data_out_big
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit.ioctl.in_val
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit.ioctl.invalid_req
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit.ioctl.no_data
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit.ioctl.not_valid_fd
…
phoenix-rtos-tests/ioctl/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/ioctl/unit
phoenix-rtos-tests/libc/printf ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/libc/printf
phoenix-rtos-tests/libc/scanf-basic ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/libc/scanf-basic
phoenix-rtos-tests/libc/stdlib ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/libc/stdlib
phoenix-rtos-tests/libuuid/unit ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/libuuid/unit
phoenix-rtos-tests/mem/mmap ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/mem/mmap
phoenix-rtos-tests/sample/test/unity ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/sample/test/unity
phoenix-rtos-tests/sys/cond ‑ armv7m7-imxrt117x-evk:phoenix-rtos-tests/sys/cond

♻️ This comment has been updated with latest results.

@ayoopierre ayoopierre force-pushed the ayopierre/grlib-can branch from 365435a to b2e7c9c Compare July 31, 2025 14:15
msg->o.err = ret;
return ret;
case can_readSync:
/* Places number of pending frames in RX cirucular buffer, if buffer cannot fit whole CAN frame */

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[codespell] reported by reviewdog 🐶
cirucular ==> circular

@ayoopierre ayoopierre force-pushed the ayopierre/grlib-can branch from b2e7c9c to 3b23cc5 Compare July 31, 2025 14:19
@ayoopierre ayoopierre force-pushed the ayopierre/grlib-can branch from 3b23cc5 to b030c67 Compare July 31, 2025 14:34
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.

3 participants