Get USB Host Controller parameters in Linux programmatically - c

I need to get some parameters related to USB Host Controllers in Linux. I made a lot of searches in the internet and the only way that I found is using pciutils lib. Each PCI device is in the structure pci_dev in pci.h:
struct pci_dev {
struct pci_dev *next; /* Next device in the chain */
u16 domain_16; /* 16-bit version of the PCI domain for backward compatibility */
/* 0xffff if the real domain doesn't fit in 16 bits */
u8 bus, dev, func; /* Bus inside domain, device and function */
/* These fields are set by pci_fill_info() */
int known_fields; /* Set of info fields already known */
u16 vendor_id, device_id; /* Identity of the device */
u16 device_class; /* PCI device class */
int irq; /* IRQ number */
pciaddr_t base_addr[6]; /* Base addresses including flags in lower bits */
pciaddr_t size[6]; /* Region sizes */
pciaddr_t rom_base_addr; /* Expansion ROM base address */
pciaddr_t rom_size; /* Expansion ROM size */
struct pci_cap *first_cap; /* List of capabilities */
char *phy_slot; /* Physical slot */
char *module_alias; /* Linux kernel module alias */
char *label; /* Device name as exported by BIOS */
int numa_node; /* NUMA node */
pciaddr_t flags[6]; /* PCI_IORESOURCE_* flags for regions */
pciaddr_t rom_flags; /* PCI_IORESOURCE_* flags for expansion ROM */
int domain; /* PCI domain (host bridge) */
/* Fields used internally */
struct pci_access *access;
struct pci_methods *methods;
u8 *cache; /* Cached config registers */
int cache_len;
int hdrtype; /* Cached low 7 bits of header type, -1 if unknown */
void *aux; /* Auxiliary data */
struct pci_property *properties; /* A linked list of extra properties */
struct pci_cap *last_cap; /* Last capability in the list */
};
I found also that I can parse pci devices as following:
struct pci_access *pacc1;
struct pci_dev *dev1;
unsigned int c1;
char namebuf1[1024], *name1;
pacc1 = pci_alloc(); /* Get the pci_access structure */
/* Set all options you want -- here we stick with the defaults */
pci_init(pacc1); /* Initialize the PCI library */
pci_scan_bus(pacc1); /* We want to get the list of devices */
for (dev1=pacc1->devices; dev1; dev1=dev1->next) /* Iterate over all devices */
{
pci_fill_info(dev1, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_CLASS); /* Fill in header info we need */
c1 = pci_read_byte(dev1, PCI_INTERRUPT_PIN); /* Read config register directly */
printf("%04x:%02x:%02x.%d vendor=%04x device=%04x class=%04x irq=%d (pin %d) base0=%lx",
dev1->domain, dev1->bus, dev1->dev, dev1->func, dev1->vendor_id, dev1->device_id,
dev1->device_class, dev1->irq, c1, (long) dev1->base_addr[0]);
/* Look up and print the full name of the device */
name1 = pci_lookup_name(pacc, namebuf1, sizeof(namebuf1), PCI_LOOKUP_DEVICE, dev1->vendor_id, dev1->device_id);
printf(" ***************** %d: (%s)\n", dev1->dev, name1);
}
pci_cleanup(pacc1); /* Close everything */
Is there a way to check in the loop if the corresponding pci device corresponds to an USB Host Controller? Or is there a simpler way to get USB Host Controller infos?

Related

Getting kernel image size in uboot

I'm attempting to create custom functionality for kernel authenticity validation on my uboot on an armv8 based platform. The method in which context I'm working in is boot_jump_linux, seen in uboot source here, around line #50.
The parameter (bootm_headers_t *images) includes the information on where the kernel is loaded in memory. With that I've been able to iterate over the specific memory area and otherwise I have everything I need, but I'm missing the information on the length of kernel data. The struct under *images references multiple relevant data structures found here:
typedef struct image_header {
uint32_t ih_magic; /* Image Header Magic Number */
uint32_t ih_hcrc; /* Image Header CRC Checksum */
uint32_t ih_time; /* Image Creation Timestamp */
uint32_t ih_size; /* Image Data Size */
uint32_t ih_load; /* Data Load Address */
uint32_t ih_ep; /* Entry Point Address */
uint32_t ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;
typedef struct image_info {
ulong start, end; /* start/end of blob */
ulong image_start, image_len; /* start of image within blob, len of image */
ulong load; /* load addr for the image */
uint8_t comp, type, os; /* compression, type of image, os type */
uint8_t arch; /* CPU architecture */
} image_info_t;
All values in the above image_header have a similar constant value, including timestamp, so that leads me to believe that they haven't been initialized. Additionally the image_info struct contains values of 0 all length related fields.
Is there some other way of determining the kernel size, or should I just fall back on to a predetermined default value?

What is my parent device and how do I get a pointer to it?

I'm writing a pseudo-driver to emulate a piece of hardware that does not yet exist. The pseudo driver will emulate some of the functionality of the hardware (obviously lying about actual underlying data). This is to test other parts of the system while waiting on hardware.
Obviously the actual hardware will have a valid parent device (it will be on a PCI bus, or USB, or something else), but my emulated device isn't hosted by any of these. However, I am not writing a top level device.
Driver registration requires a pointer to a struct device *parent. How do I get this information for a virtual driver?
You could allocate a dummy platform device and set up a platform device driver for testing typical driver "probe" and "remove" functionality. Here is a somewhat minimal example:
// SPDX-License-Identifier: GPL-2.0 OR MIT
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
MODULE_AUTHOR("Ian Abbott");
MODULE_LICENSE("Dual MIT/GPL");
MODULE_DESCRIPTION("FooBar driver example with dummy platform device");
#define FOOBAR_NAME "foobar"
/* Private data for a foobar device. */
struct foobar_private {
/* ... */
struct device *hwdev; /* Pointer to hardware device. */
/* ... */
};
static int foobar_platform_probe(struct platform_device *pdev)
{
struct device *hwdev = &pdev->dev;
struct foobar_private *foobar;
dev_info(hwdev, "probe\n");
/* Allocate private data. */
foobar = kzalloc(sizeof(*foobar), GFP_KERNEL);
if (!foobar)
return -ENOMEM;
/* Set up private data. */
foobar->hwdev = hwdev;
/* Link private data to hardware device. */
dev_set_drvdata(hwdev, foobar);
/* ... other stuff ... */
return 0;
}
static int foobar_platform_remove(struct platform_device *pdev)
{
struct device *hwdev = &pdev->dev;
struct foobar_private *foobar = dev_get_drvdata(hwdev);
dev_info(hwdev, "remove\n");
dev_set_drvdata(hwdev, NULL);
/* ... other stuff ... */
kfree(foobar);
return 0;
}
/* Platform driver. */
static struct platform_driver foobar_driver = {
.probe = foobar_platform_probe,
.remove = foobar_platform_remove,
.driver = {
.name = FOOBAR_NAME,
.owner = THIS_MODULE,
},
};
/* Pointer to dummy platform device for testing purposes. */
static struct platform_device *foobar_test_device;
static int __init foobar_init(void)
{
int err;
/* Register the platform driver. */
err = platform_driver_register(&foobar_driver);
if (err)
return err;
/*
* Create a dummy platform device for testing.
* Make the platform device name the same as the driver name
* so that the driver's "probe" function will be called when
* the device is registered later.
*
* Note: PLATFORM_DEVID_AUTO allocates an "automatic" instance
* ID for the device. Can use PLATFORM_DEVID_NONE for no instance
* ID (for a single device), or use a non-zero integer to set a
* specific instance ID.
*/
foobar_test_device =
platform_device_alloc(FOOBAR_NAME, PLATFORM_DEVID_AUTO);
if (!foobar_test_device) {
err = -ENOMEM;
goto err_unregister_driver;
}
/*
* Can call functions such as platform_device_add_resources(),
* platform_device_add_data(), platform_device_add_properties(),
* etc. here for playing around.
*/
/*
* Add (register) the dummy platform device.
* This should result in the driver's "probe" function being called.
*/
err = platform_device_add(foobar_test_device);
if (err)
goto err_free_device;
return 0;
err_free_device:
/* Undo platform_device_alloc(). */
platform_device_put(foobar_test_device);
err_unregister_driver:
/* Undo platform_driver_register(). */
platform_driver_unregister(&foobar_driver);
return err;
}
static void __exit foobar_exit(void)
{
/*
* Unregister the dummy platform device used for testing.
* This should result in the driver's "remove" function being called.
*/
platform_device_unregister(foobar_test_device);
/* Unregister the platform driver. */
platform_driver_unregister(&foobar_driver);
}
module_init(foobar_init);
module_exit(foobar_exit);
If the struct platform_device's dev.parent member is NULL, platform_device_add() will change it to &platform_device.

Cannot run a large structure filled with arrays win C

I'm building a SAE J1939 library for embedded systems such as Arduino, STM32, AVR etc.
But I have an issue I don't understand. First when I compile. No error!
But when I run, I get this assembler error. It's all about the J1939 struct.
Why does this happen? Is the heap to small?
Can't find a source file at
"C:\mingw810\i686-810-posix-dwarf-rt_v6-rev0\build\gcc-8.1.0\i686-w64-mingw32\libgcc/../../../../../src/gcc-8.1.0/libgcc/config/i386/cygwin.S"
Locate the file or edit the source lookup path to include its
location.
Run this code below to reproduce the error:
#include <stdio.h>
#include <stdlib.h>
#include "stdint.h"
/* PGN: 0x00E800 - Storing the Acknowledgement from the reading process */
struct Acknowledgement {
uint8_t control_byte; /* This indicates the status of the requested information about PGN: */
uint8_t group_function_value; /* The function code that specify cause of the control byte e.g time out or aborted */
uint8_t address; /* Address from the ECU where the acknowledgement is comming from */
uint32_t PGN_of_requested_info; /* Information request about the PGN */
};
/* PGN: 0x00EC00 - Storing the Transport Protocol Connection Management from the reading process */
struct TP_CM {
uint8_t control_byte; /* What type of message are we going to send */
uint16_t total_message_size; /* Total bytes our complete message includes */
uint8_t number_of_packages; /* How many times we are going to send packages via TP_DT */
uint32_t PGN_of_the_packeted_message; /* Our message is going to activate a PGN */
};
/* PGN: 0x00EB00 - Storing the Transport Protocol Data Transfer from the reading process */
struct TP_DT {
uint8_t sequence_number; /* When this sequence number is the same as number_of_packages from TP_CM, then we have our complete message */
uint8_t data[7][256]; /* Package data of 2D array where first index is data0 -> data6 and second index is sequence of the data */
};
/* PGN: 0x00EE00 - Storing the Address claimed from the reading process */
struct Name {
uint32_t identity_number; /* Specify the ECU serial ID - 0 to 2097151 */
uint16_t manufacturer_code; /* Specify the ECU manufacturer code - 0 to 2047 */
uint8_t function_instance; /* Specify the ECU function number - 0 to 31 */
uint8_t ECU_instance; /* Specify the ECU number - 0 to 7 */
uint8_t function; /* Specify the ECU function - 0 to 255 */
uint8_t vehicle_system; /* Specify the type of vehicle where ECU is located - 0 to 127 */
uint8_t arbitrary_address_capable; /* Specify if the ECU have right to change address if addresses conflicts - 0 to 1 */
uint8_t industry_group; /* Specify the group where this ECU is located - 0 to 7 */
uint8_t vehicle_system_instance; /* Specify the vehicle system number - 0 to 15 */
};
/* PGN: 0x00FECA - Storing the DM1 Active diagnostic trouble codes from the reading process */
struct DM1 {
/* These are SAE lamps can have 1 = ON and 0 = OFF */
uint8_t SAE_lamp_status_malfunction_indicator;
uint8_t SAE_lamp_status_red_stop;
uint8_t SAE_lamp_status_amber_warning;
uint8_t SAE_lamp_status_protect_lamp;
uint8_t SAE_flash_lamp_malfunction_indicator;
uint8_t SAE_flash_lamp_red_stop;
uint8_t SAE_flash_lamp_amber_warning;
uint8_t SAE_flash_lamp_protect_lamp;
/* Fault location, problem and codes */
uint32_t SPN; /* Location where the fault exist */
uint8_t FMI; /* Type of problem */
uint8_t SPN_conversion_method; /* If SPN_conversion_method = 1 that means Diagnostics Trouble Code are aligned using a newer conversion method. If SPN_conversion_method = 0 means one of the three Diagnostics Trouble Code conversion methods is used and ECU manufacture shall know which of the three methods is used */
uint8_t occurence_count; /* This tells how many times failure has occurred. Every time fault goes from inactive to active, the occurence_count is incremented by 1. If fault becomes active for more than 126 times the occurence_count remains 126 */
};
/* PGN: 0x00D800 - Storing the DM15 response from the reading process */
struct DM15 {
uint16_t number_of_allowed_bytes; /* How many bytes we are allowed to write or read to */
uint8_t status; /* Status of the response */
uint32_t EDC_parameter; /* Status code */
uint8_t EDCP_extention; /* Describe how we should interpret the EDC parameter as a status code or error code */
uint16_t seed; /* Response of the key if we need more key or no key at all */
};
/* PGN: 0x00D700 - Storing the DM16 binary data transfer from the reading process */
struct DM16 {
uint8_t number_of_occurences; /* How many bytes we have sent */
uint8_t raw_binary_data[256]; /* Here we store the bytes */
};
/* Storing the error codes from the reading process */
struct DM {
uint8_t errors_dm1_active; /* How many errors of DM1 we have right now */
uint8_t errors_dm2_active; /* How many errors of DM2 is active */
struct DM1 dm1[256]; /* dm1 can contains multiple error messages */
struct DM1 dm2[256]; /* dm2 contains previously active errors from dm1 */
struct DM15 dm15; /* dm15 is the memory access response from DM14 memory request */
struct DM16 dm16; /* dm16 is the binary data transfer after DM15 memory response (if it was proceeded) */
/* Add more DM here */
};
/* PGN: 0x00FEDA - Storing the software identification from the reading process */
struct Software_identification {
uint8_t length_of_each_identification; /* The length of each identification - Not part of J1939 standard */
uint8_t number_of_fields; /* How many numbers contains in the identifications array */
uint8_t identifications[256]; /* This can be for example ASCII */
};
/* PGN: 0x00FDC5 - Storing the ECU identification from the reading process */
struct ECU_identification {
uint8_t length_of_each_field; /* The real length of the fields - Not part of J1939 standard */
uint8_t ecu_part_number[256]; /* ASCII field */
uint8_t ecu_serial_number[256]; /* ASCII field */
uint8_t ecu_location[256]; /* ASCII field */
uint8_t ecu_type[256]; /* ASCII field */
uint8_t ecu_manufacturer[256]; /* ASCII field */
uint8_t ecu_hardware_version[256]; /* ASCII field */
};
/* PGN: 0x00FEEB - Storing the component identification from the reading process */
struct Component_identification {
uint8_t length_of_each_field; /* The real length of the fields - Not part of J1939 standard */
uint8_t component_product_date[256]; /* ASCII field */
uint8_t component_model_name[256]; /* ASCII field */
uint8_t component_serial_number[256]; /* ASCII field */
uint8_t component_unit_name[256]; /* ASCII field */
};
/* PGN: 0x00FE30 (65072) to 0x00FE3F (65087) */
struct Auxiliary_valve_command {
uint8_t standard_flow; /* Command flow */
uint8_t fail_safe_mode; /* If the user want the valve to go to neutral */
uint8_t valve_state; /* Retract, Extend, Neutral, Init, Error etc */
};
/* PGN: 0x00FE10 (65040) to 0x00FE1F (65055) */
struct Auxiliary_valve_estimated_flow {
uint8_t extend_estimated_flow_standard; /* A measurement */
uint8_t retract_estimated_flow_standard; /* A measurement */
uint8_t valve_state; /* Retract, Extend, Neutral, Init, Error etc */
uint8_t fail_safe_mode; /* The mode if we are going to use fail safe mode or not */
uint8_t limit; /* Enter a limit code */
};
/* PGN: 0x00C400 (50176) */
struct General_purpose_valve_command {
uint8_t standard_flow; /* Command flow */
uint8_t fail_safe_mode; /* If the user want the valve to go to neutral */
uint8_t valve_state; /* Retract, Extend, Neutral, Init, Error etc */
uint16_t extended_flow; /* Another command flow */
};
/* PGN: 0x00C600 (50688) */
struct General_purpose_valve_estimated_flow {
uint8_t extend_estimated_flow_standard; /* A measurement */
uint8_t retract_estimated_flow_standard; /* A measurement */
uint8_t valve_state; /* Retract, Extend, Neutral, Init, Error etc */
uint8_t fail_safe_mode; /* The mode if we are going to use fail safe mode or not */
uint8_t limit; /* Enter a limit code */
uint16_t extend_estimated_flow_extended; /* A measurement */
uint16_t retract_estimated_flow_extended; /* A measurement */
};
struct Auxiliary_valve_measured_position {
uint16_t measured_position_procent; /* Procent position */
uint8_t valve_state; /* Retract, Extend, Neutral, Init, Error etc */
uint16_t measured_position_micrometer; /* Micrometer position */
};
typedef struct {
/* For information about other ECU */
uint8_t number_of_ECU;
uint8_t number_of_cannot_claim_address;
uint8_t ECU_address[256];
struct Acknowledgement acknowledgement[256];
struct TP_CM tp_cm[256];
struct TP_DT tp_dt[256];
struct Name name[256];
struct DM dm[256];
struct Software_identification software_identification[256];
struct ECU_identification ecu_identification[256];
struct Component_identification component_identification[256];
struct Auxiliary_valve_estimated_flow auxiliary_valve_estimated_flow[256][16];
struct General_purpose_valve_estimated_flow general_purpose_valve_estimated_flow[256];
struct Auxiliary_valve_measured_position auxiliary_valve_measured_position[256][16];
/* For information about this ECU */
struct Name this_name;
uint8_t this_ECU_address;
struct DM this_dm;
struct Software_identification this_software_identification;
struct ECU_identification this_ecu_identification;
struct Component_identification this_component_identification;
struct Auxiliary_valve_command this_auxiliary_valve_command[16];
struct General_purpose_valve_command this_general_purpose_valve_command;
} J1939;
int main(void) {
J1939 j1939;
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
return EXIT_SUCCESS;
}
This information is not a compilation error. You execute a debugger and try to debug a part of program without located sources. This could happen if your program stops in a compiled library. Then we can use a assembler instruction only. As mentioned above try to set breakpoint into your main() funcion.

Call different CAN-controllers in one function?

My first question here. I´m no proffesional programmer at all. Just for fun at home so I don´t really know the right terminology for what I´m about to ask.
I want to create a CAN-bus gateway and I have the NXP DEVKIT-MPC5748G. All the CAN-busses are set-up and working for both tx and rx. Now I want to create a function for manipulating the different CAN-controllers. Theres 8 of them so I was hoping of not write 8 equal functions only having what CAN-controller to use differ.
You setup the controllers like this:
CAN_1.CTRL1.B.CLKSRC = 0;
Just an example for setting the clock source.
CAN_1 has a macro like this:
#define CAN_1 (*(volatile struct CAN_1_7_tag *) 0xFBEC0000UL)
In that struct there is a hole lot of unions for accessing all the registers. Now I want to write a function that I can pass a parameter to tell what CAN-controller to use. I can use a switch/case style way of doing it but that code will be long and ugly.
I want to do something like this:
void Tx_Msg("type???" gwport, int mb, uint32_t id) {
gwport.[mb].CS.B.CODE = 0x8; }
But I cant figure out how to do it. Can it be done?
Thankfull for all help in the right direction. :)
Best regards, Joakim
EDIT to clarify
CAN_1_7_tag struct:
struct CAN_1_7_tag {
CAN_MCR_tag MCR; /* Module Configuration Register */
CAN_CTRL1_tag CTRL1; /* Control 1 register */
CAN_TIMER_tag TIMER; /* Free Running Timer */
uint8_t CAN_reserved0[4];
CAN_RXMGMASK_tag RXMGMASK; /* Rx Mailboxes Global Mask Register */
CAN_RX14MASK_tag RX14MASK; /* Rx 14 Mask register */
CAN_RX15MASK_tag RX15MASK; /* Rx 15 Mask register */
CAN_ECR_tag ECR; /* Error Counter */
CAN_ESR1_tag ESR1; /* Error and Status 1 register */
CAN_IMASK2_tag IMASK2; /* Interrupt Masks 2 register */
CAN_IMASK1_tag IMASK1; /* Interrupt Masks 1 register */
CAN_IFLAG2_tag IFLAG2; /* Interrupt Flags 2 register */
CAN_IFLAG1_tag IFLAG1; /* Interrupt Flags 1 register */
CAN_CTRL2_tag CTRL2; /* Control 2 register */
CAN_ESR2_tag ESR2; /* Error and Status 2 register */
uint8_t CAN_reserved1[8];
CAN_CRCR_tag CRCR; /* CRC Register */
CAN_RXFGMASK_tag RXFGMASK; /* Rx FIFO Global Mask register */
CAN_RXFIR_tag RXFIR; /* Rx FIFO Information Register */
CAN_CBT_tag CBT; /* CAN Bit Timing Register */
uint8_t CAN_reserved2[24];
CAN_IMASK3_tag IMASK3; /* Interrupt Masks 3 Register */
uint8_t CAN_reserved3[4];
CAN_IFLAG3_tag IFLAG3; /* Interrupt Flags 3 Register */
uint8_t CAN_reserved4[8];
CAN_MB_tag MB[64];
uint8_t CAN_reserved5[1024];
CAN_RXIMR_tag RXIMR[96]; /* Rx Individual Mask Registers */
uint8_t CAN_reserved6[512];
CAN_FDCTRL_tag FDCTRL; /* CAN FD Control Register */
CAN_FDCBT_tag FDCBT; /* CAN FD Bit Timing Register */
CAN_FDCRC_tag FDCRC; /* CAN FD CRC Register */
};
Example for MCR register. All registers works the same way.
typedef union CAN_MCR_union_tag { /* Module Configuration Register */
vuint32_t R;
struct {
vuint32_t MDIS:1; /* Module Disable */
vuint32_t FRZ:1; /* Freeze Enable */
vuint32_t RFEN:1; /* Rx FIFO Enable */
vuint32_t HALT:1; /* Halt FlexCAN */
vuint32_t NOTRDY:1; /* FlexCAN Not Ready */
vuint32_t WAKMSK:1; /* Wake Up Interrupt Mask */
vuint32_t SOFTRST:1; /* Soft Reset */
vuint32_t FRZACK:1; /* Freeze Mode Acknowledge */
vuint32_t SUPV:1; /* Supervisor Mode */
vuint32_t SLFWAK:1; /* Self Wake Up */
vuint32_t WRNEN:1; /* Warning Interrupt Enable */
vuint32_t LPMACK:1; /* Low-Power Mode Acknowledge */
vuint32_t WAKSRC:1; /* Wake Up Source */
vuint32_t _unused_18:1;
vuint32_t SRXDIS:1; /* Self Reception Disable */
vuint32_t IRMQ:1; /* Individual Rx Masking And Queue Enable */
vuint32_t DMA:1; /* DMA Enable */
vuint32_t _unused_14:1;
vuint32_t LPRIOEN:1; /* Local Priority Enable */
vuint32_t AEN:1; /* Abort Enable */
vuint32_t FDEN:1; /* CAN FD operation enable */
vuint32_t _unused_10:1;
vuint32_t IDAM:2; /* ID Acceptance Mode */
vuint32_t _unused_7:1;
vuint32_t MAXMB:7; /* Number Of The Last Message Buffer */
} B;
} CAN_MCR_tag;
Hope this is what you asked for.
If CAN_1 is define as:
#define CAN_1 (*(volatile struct CAN_1_7_tag *) 0xFBEC0000UL)
Then CAN_1 is a structure of type CAN_1_7_tag which is located at 0xFBEC0000UL.
The volatile qualifier is here to indicate to the compiler that is should not optimize anything relatives to the CAN_1 as it might be changed by other threads.
You can pass the CAN-controller as a pointer:
void Tx_Msg(volatile struct CAN_1_7_tag *p_gwport, int mb, uint32_t id)
{
p_gwport->CTRL1.B.CLKSRC = 0;
p_gwport->MB[mb].CS.B.CODE = 0x8;
}
Then when calling this function to send a message from a specific CAN-controller, you can use:
Tx_Msg(&CAN_1, 12, 25);
Tx_Msg(&CAN_4, 21, 45);
Thanks one more time for the help. The CAN gateway is up and running as a prototype.
This is my "final" code.
/********************************************************************************/
/* Tx function for FlexCAN 1-7 */
/********************************************************************************/
void Tx_Msg_1_7(volatile struct CAN_1_7_tag *port, uint32_t mb, uint32_t dlc, uint32_t id, uint8_t txData[])
{
int i = 0; // Used in for loops
port->MB[mb].CS.B.CODE = 0x8; // MB TX inactive
port->MB[mb].CS.B.DLC = dlc; // Message length max 8 bytes
port->MB[mb].CS.B.RTR = 0; // Remote frame disable
port->MB[mb].CS.B.SRR = 1; // Not used with standard id
if (id > 0x7FF) // CAN id 29 bits
{
port->MB[mb].CS.B.IDE = 1; // EXT CAN id
port->MB[mb].ID.B.ID_STD = id >> 18 & 0x7FF; // CAN id (11 bits)
port->MB[mb].ID.B.ID_EXT = id & 0x3FFFF; // CAN id (18 bits)
}
else // CAN id 11 bits
{
port->MB[mb].CS.B.IDE = 0; // STD CAN id
port->MB[mb].ID.B.ID_STD = id; // CAN id (11 bits)
port->MB[mb].ID.B.ID_EXT = 0; // CAN id (18 bits), always 0
}
for(i = 0; i < dlc; i++)
{
port->MB[mb].DATA.B[i] = txData[i];
}
port->MB[mb].CS.B.CODE = 0xC; // MB once transmit data
}

error: dereferencing pointer to incomplete type when accessing struct

I am not sure why this is happening. I am doing an assignment and the code somehow does not compile.
This is the header file
#include <stdint.h>
typedef struct
{
uint8_t jump_code[3]; /* Ignore this */
char oemname[8]; /* Might as well ignore this one too */
uint8_t ssize[2]; /* Sector size in bytes */
uint8_t csize; /* Cluster size in sectors */
uint8_t reserved[2]; /* Number of reserved sectors for boot sectors */
uint8_t numfat; /* Number of FATs */
uint8_t numroot[2]; /* Number of Root directory entries */
uint8_t sectors16[2]; /* number of sectors in the file system */
uint8_t media[1]; /* Media descriptor type */
uint8_t sectperfat16[2];/* Number of sectors per FAT */
uint8_t sectpertrack[2];/* Number of sectors per track */
uint8_t heads[2]; /* Number of heads */
uint8_t prevsect[2]; /* Number of sectors before FS partition */
uint8_t ignore[482]; /* Ignore these */
} boot_sect_t;
This is the part that gives the error:
struct boot_sect_t* boot = malloc(sizeof(boot_sect_t));
boot->ssize[0] = buffer[11]; //error here
boot->ssize[1] = buffer[12]; //error here
The error is:
error: dereferencing pointer to incomplete type when accessing struct
you need to change
struct boot_sect_t* boot = malloc(sizeof(boot_sect_t));
to
boot_sect_t* boot = malloc(sizeof(boot_sect_t));
boot_sect_t is already a typedef. no need to write struct boot_sect_t.

Resources