Home Learning Paths ECU Lab Assessments Interview Preparation Arena Pricing Log In Sign Up

Function Pointer Syntax and typedef

Cfn_ptr_syntax.c
#include 

/* Function pointer type: points to functions taking (uint8_t) returning void */
typedef void (*EventHandler_t)(uint8_t event_id);

/* Declare a function pointer variable */
EventHandler_t g_can_rx_handler = NULL;

/* Assign and call */
void OnCanRx(uint8_t evt) { /* handle CAN RX */ (void)evt; }
g_can_rx_handler = OnCanRx;
if (g_can_rx_handler != NULL) {
    g_can_rx_handler(0x01u);   /* call through pointer */
}

/* Function pointer to function with multiple parameters */
typedef Std_ReturnType (*ReadCallback_t)(uint8_t channel, uint16_t *out);

/* Array of function pointers: select handler by index */
typedef void (*IrqHandler_t)(void);
extern void Timer0_ISR(void);
extern void Can0_ISR(void);
extern void Spi0_ISR(void);

const IrqHandler_t irq_table[] = {
    Timer0_ISR,   /* IRQ 0 */
    Can0_ISR,     /* IRQ 1 */
    Spi0_ISR,     /* IRQ 2 */
};

Dispatch Table Pattern

Cdispatch_table.c
#include 
#include "Std_Types.h"

/* UDS service dispatch: map SID to handler function */
typedef Std_ReturnType (*UdsHandler_t)(const uint8_t *req, uint16_t req_len,
                                        uint8_t *resp, uint16_t *resp_len);

Std_ReturnType Uds_Handle0x10(const uint8_t *req, uint16_t req_len,
                                uint8_t *resp, uint16_t *resp_len);
Std_ReturnType Uds_Handle0x22(const uint8_t *req, uint16_t req_len,
                                uint8_t *resp, uint16_t *resp_len);
Std_ReturnType Uds_Handle0x27(const uint8_t *req, uint16_t req_len,
                                uint8_t *resp, uint16_t *resp_len);

typedef struct {
    uint8_t      sid;
    UdsHandler_t handler;
} UdsServiceEntry_t;

static const UdsServiceEntry_t UDS_DISPATCH[] = {
    { 0x10u, Uds_Handle0x10 },
    { 0x22u, Uds_Handle0x22 },
    { 0x27u, Uds_Handle0x27 },
};
#define UDS_SERVICE_COUNT (sizeof(UDS_DISPATCH) / sizeof(UDS_DISPATCH[0]))

Std_ReturnType Uds_Dispatch(const uint8_t *req, uint16_t req_len,
                              uint8_t *resp, uint16_t *resp_len)
{
    uint8_t sid = req[0];
    for (uint8_t i = 0u; i < (uint8_t)UDS_SERVICE_COUNT; i++) {
        if (UDS_DISPATCH[i].sid == sid) {
            return UDS_DISPATCH[i].handler(req, req_len, resp, resp_len);
        }
    }
    return E_NOT_OK;  /* NRC 0x11: serviceNotSupported */
}

Callback Registration Pattern (AUTOSAR style)

Ccallbacks.c
/* AUTOSAR callback registration: BSW module notifies application */
#include "Std_Types.h"

/* Callback type: application implements; BSW calls */
typedef void (*Can_RxIndicationFuncType)(uint8_t controllerId,
                                          uint16_t id,
                                          const uint8_t *data,
                                          uint8_t dlc);

/* BSW module state */
static Can_RxIndicationFuncType g_rxIndication = NULL;

/* BSW API: application registers callback at init */
void Can_RegisterRxIndication(Can_RxIndicationFuncType callback)
{
    g_rxIndication = callback;
}

/* BSW internal: called from CAN ISR */
void Can_InternalRxDispatch(uint8_t ctrl, uint16_t id,
                              const uint8_t *data, uint8_t dlc)
{
    if (g_rxIndication != NULL) {
        g_rxIndication(ctrl, id, data, dlc);
    }
}

/* Application code: */
void App_CanRxCallback(uint8_t ctrl, uint16_t id,
                        const uint8_t *data, uint8_t dlc)
{
    if (id == 0x200u) {
        /* process vehicle speed CAN message */
    }
}
/* In App_Init(): Can_RegisterRxIndication(App_CanRxCallback); */

MISRA-C:2012 Rules on Function Pointers

RuleCategoryRequirement
Rule 11.1RequiredConversions shall not be performed between pointer-to-function and any other type
Rule 15.5AdvisoryA function should have a single point of exit (return statement) — applies to functions called via pointer
Dir 4.9AdvisoryFunction-like macros should not be used where a function pointer pattern is cleaner
Rule 8.2RequiredFunction types shall be explicitly declared — always typedef function pointer types

Summary

Function pointers are the primary abstraction mechanism in C-based AUTOSAR code: dispatch tables replace large switch statements, callback registration decouples BSW from application, and interface structs (arrays of function pointers) implement runtime polymorphism. The key discipline is always checking for NULL before calling through a function pointer — in safety-critical code, an unchecked NULL dereference through a function pointer triggers a HardFault with no useful call stack. Always typedef function pointer types for readability and MISRA compliance.

🔬 Deep Dive — Core Concepts Expanded

This section builds on the foundational concepts covered above with additional technical depth, edge cases, and configuration nuances that separate competent engineers from experts. When working on production ECU projects, the details covered here are the ones most commonly responsible for integration delays and late-phase defects.

Key principles to reinforce:

  • Configuration over coding: In AUTOSAR and automotive middleware environments, correctness is largely determined by ARXML configuration, not application code. A correctly implemented algorithm can produce wrong results due to a single misconfigured parameter.
  • Traceability as a first-class concern: Every configuration decision should be traceable to a requirement, safety goal, or architecture decision. Undocumented configuration choices are a common source of regression defects when ECUs are updated.
  • Cross-module dependencies: In tightly integrated automotive software stacks, changing one module's configuration often requires corresponding updates in dependent modules. Always perform a dependency impact analysis before submitting configuration changes.

🏭 How This Topic Appears in Production Projects

  • Project integration phase: The concepts covered in this lesson are most commonly encountered during ECU integration testing — when multiple software components from different teams are combined for the first time. Issues that were invisible in unit tests frequently surface at this stage.
  • Supplier/OEM interface: This is a topic that frequently appears in technical discussions between Tier-1 ECU suppliers and OEM system integrators. Engineers who can speak fluently about these details earn credibility and are often brought into critical design review meetings.
  • Automotive tool ecosystem: Vector CANoe/CANalyzer, dSPACE tools, and ETAS INCA are the standard tools used to validate and measure the correct behaviour of the systems described in this lesson. Familiarity with these tools alongside the conceptual knowledge dramatically accelerates debugging in real projects.

⚠️ Common Mistakes and How to Avoid Them

  1. Assuming default configuration is correct: Automotive software tools ship with default configurations that are designed to compile and link, not to meet project-specific requirements. Every configuration parameter needs to be consciously set. 'It compiled' is not the same as 'it is correctly configured'.
  2. Skipping documentation of configuration rationale: In a 3-year ECU project with team turnover, undocumented configuration choices become tribal knowledge that disappears when engineers leave. Document why a parameter is set to a specific value, not just what it is set to.
  3. Testing only the happy path: Automotive ECUs must behave correctly under fault conditions, voltage variations, and communication errors. Always test the error handling paths as rigorously as the nominal operation. Many production escapes originate in untested error branches.
  4. Version mismatches between teams: In a multi-team project, the BSW team, SWC team, and system integration team may use different versions of the same ARXML file. Version management of all ARXML files in a shared repository is mandatory, not optional.

📊 Industry Note

Engineers who master both the theoretical concepts and the practical toolchain skills covered in this course are among the most sought-after professionals in the automotive software industry. The combination of AUTOSAR standards knowledge, safety engineering understanding, and hands-on configuration experience commands premium salaries at OEMs and Tier-1 suppliers globally.

← PreviousStructures, Unions & Bit FieldsNext →Preprocessor, Macros & Conditional Compilation