Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I am working on a C project for the university where a CoAP server is to be hosted on a TM4C129EXL. It is particularly important to choose a FreeRTOS operating system. Unfortunately, I had to learn that Texas Instruments has stopped supporting FreeRTOS. There are no options for me to switch to another operating system. It is for this reason that I turn to you.
I'm looking for a sample program in which Free RTOS is executed on a TM4C129EXL board. In the best case, I would be happy about a Code Composer Studio Project, as this is the IDE we work with from the university.
If you do not have any sample code available, I would be happy to receive any other information regarding FreeRTOS and CoAP of course with reference to the TM4C129EXL.
You did not specify if you had any requirements in terms of FreeRTOS version, but you can either:
use the demo provided in file SW-EK-TM4C1294XL-2.1.4.178.exe available on TI WEB site as is - you will find it in directory examples\boards\ek-tm4c1294xl-boostxl-senshub\senshub_iot
use this example as a basis to use a more recent version of FreeRTOS: you just would have to replace FreeRTOS source code by the most recent one, and maybe to modify some code in the demo: some function names/signatures may have changed across major versions.
The procedure hereafter describes step by step how to create a minimalist FreeRTOS program with Code Composer Studio 10.3.0 and FreeRTOS v202104.00 in a Windows 10 environment using the second approach. You may have to adjust the drive letter to you specific setup, I am using D: for the purpose of this example..
Download Code Composer Studio 10.3.0, FreeRTOS v202104.00 and SW-EK-TM4C1294XL-2.1.4.178.exe.
Install Code Composer Studio with support for the Tiva-C MCU familly. When prompted for a workspace name, specify D:\ti\workspace_v10.
Unzip FreeRTOSv202104.00.zipinto D:\.
Unzip SW-EK-TM4C1294XL-2.1.4.178.exe into D:\SW-EK-TM4C1294XL-2.1.4.178.
Launch CCS
Use the menu item File/New/CCS Project, and create an 'Empty Project (with main.c).
[]
Click on the Finishbutton.
Create the following directories: D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\driverlib D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\inc D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\include D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\portable\GCC D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\portable\GCC\ARM_CM4F D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\portable\MemMang
Copy D:\SW-EK-TM4C1294XL-2.1.4.178\examples\boards\ek-tm4c1294xl-boostxl-senshub\senshub_iot\FreeRTOSConfig.h into D:\ti\workspace_v10\TM4C129EXL-FreeRTOS
Copy all .h files from D:\SW-EK-TM4C1294XL-2.1.4.178\driverlib into D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\driverlib.
Copy D:\SW-EK-TM4C1294XL-2.1.4.178\driverlib\gcc\libdriver.a into D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\driverlib.
Copy all .hfiles from D:\SW-EK-TM4C1294XL-2.1.4.178\inc into D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\inc.
Copy all files present in D:\FreeRTOSv202104.00\FreeRTOS\Source\include into D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\include.
Copy all .cfiles present in D:\FreeRTOSv202104.00\FreeRTOS\Source into D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel.
Copy all file present in D:\FreeRTOSv202104.00\FreeRTOS\Source\portable\GCC\ARM_CM4F into D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\portable\GCC\ARM_CM4F
Copy D:\FreeRTOSv202104.00\FreeRTOS\Source\portable\MemMang\heap_4.c into D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\portable\MemMang.
Edit D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\main.c, and replace its content by:
#include "FreeRTOS.h"
#include "task.h"
extern void prvSetupHardware();
extern void main_blinky();
int main(void)
{
/* Configure the hardware ready to run the demo. */
prvSetupHardware();
main_blinky();
/* Don't expect to reach here. */
return 0;
}
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName)
{
while(1)
{
}
}
Create a new file named D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\blinky.c with the following content:
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "FreeRTOS.h"
#include "task.h"
#include "sysctl.h"
static void prvLedToggleTask();
/* Priorities at which the tasks are created. */
#define mainTOGGLE_LED_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define TOGGLE_LED_DELAY_MS 200
void main_blinky()
{
/* create task */
xTaskCreate( prvLedToggleTask, "LED", configMINIMAL_STACK_SIZE, NULL, mainTOGGLE_LED_PRIORITY, NULL );
/* Start the tasks and timer running. */
vTaskStartScheduler();
}
static void prvLedToggleTask( void *pvParameters )
{
// Remove compiler warning about unused parameter. */
( void ) pvParameters;
for( ;; )
{
//
// Turn on the LED.
//
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
// Wait a bit
vTaskDelay( TOGGLE_LED_DELAY_MS);
//
// Turn off the LED.
//
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0x0);
// Wait a bit
vTaskDelay( TOGGLE_LED_DELAY_MS );
}
}
uint32_t g_ui32SysClock;
void prvSetupHardware()
{
// Configure PLL
g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);
//
// Enable the GPIO port that is used for the on-board LED.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
//
// Check if the peripheral access is enabled.
//
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPION))
{
}
//
// Enable the GPIO pin for the LED (PN0). Set the direction as output, and
// enable the GPIO pin for digital function.
//
GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);
}
Edit tm4c1294ncpdt_startup_ccs_gcc.c: add the following lines after the line containing static void IntDefaultHandler(void);
extern void xPortPendSVHandler(void);
extern void vPortSVCHandler(void);
extern void xPortSysTickHandler(void);
The resulting code should look like:
void ResetISR(void);
static void NmiSR(void);
static void FaultISR(void);
static void IntDefaultHandler(void);
extern void xPortPendSVHandler(void);
extern void vPortSVCHandler(void);
extern void xPortSysTickHandler(void);
Edit tm4c1294ncpdt_startup_ccs_gcc.c: replace the default interrupt handler by the FreeRTOS one in array g_pfnVectors[].
Original code:
void (* const g_pfnVectors[])(void) =
{
(void (*)(void))((uint32_t)pui32Stack + sizeof(pui32Stack)),
// The initial stack pointer
ResetISR, // The reset handler
NmiSR, // The NMI handler
FaultISR, // The hard fault handler
IntDefaultHandler, // The MPU fault handler
IntDefaultHandler, // The bus fault handler
IntDefaultHandler, // The usage fault handler
0, // Reserved
0, // Reserved
0, // Reserved
0, // Reserved
IntDefaultHandler, // SVCall handler
IntDefaultHandler, // Debug monitor handler
0, // Reserved
IntDefaultHandler, // The PendSV handler
IntDefaultHandler, // The SysTick handler
Resulting code:
void (* const g_pfnVectors[])(void) =
{
(void (*)(void))((uint32_t)pui32Stack + sizeof(pui32Stack)),
// The initial stack pointer
ResetISR, // The reset handler
NmiSR, // The NMI handler
FaultISR, // The hard fault handler
IntDefaultHandler, // The MPU fault handler
IntDefaultHandler, // The bus fault handler
IntDefaultHandler, // The usage fault handler
0, // Reserved
0, // Reserved
0, // Reserved
0, // Reserved
vPortSVCHandler, // SVCall handler
IntDefaultHandler, // Debug monitor handler
0, // Reserved
xPortPendSVHandler, // The PendSV handler
xPortSysTickHandler, // The SysTick handler
Edit the project properties for the GCC Compiler directories, and add the following directories: ${workspace_loc:/${ProjName}/FreeRTOS-Kernel/include} ${workspace_loc:/${ProjName}/FreeRTOS-Kernel/portable/GCC/ARM_CM4F} ${workspace_loc:/${ProjName} ${workspace_loc:/${ProjName}/driverlib} and click on the Apply and close button.
Edit D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOSConfig.h and delete the following lines:
#define configGENERATE_RUN_TIME_STATS 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() \
g_vulRunTimeStatsCountValue = 0ul
#define portGET_RUN_TIME_COUNTER_VALUE() g_vulRunTimeStatsCountValue
Edit the GCC compiler Command-line pattern and add the -mfloat-abi=hard option after ${flags} in the Command-line pattern:
${command} ${flags} -mfloat-abi=hard ${output_flag}${output} ${inputs}
Edit the GNU Linker Command-line pattern and add the -mfloat-abi=hard option after ${flags}:>br/>
${command} ${flags} -mfloat-abi=hard ${output_flag}${output} ${inputs}
Edit the GCC Linker libraries: add libdriver.a to the -l option, and ${workspace_loc:/${ProjName}/driverlib} to the -L option, then click on the Apply and close button.
Build your project - it should build without any errors.
Flash your project by running it.
In my case, I had to stop the project and to press the board resetbutton in order to the program to start.
Finally, the LED should start blinking every 200ms.
The complete list of files in the project once the project 'cleaned' should ultimately be:
Folder PATH listing for volume DATA
Volume serial number is 0E12-BCA2
D:.
| .ccsproject
| .cproject
| .project
| blinky.c
| FreeRTOSConfig.h
| main.c
| tm4c1294ncpdt.lds
| tm4c1294ncpdt_startup_ccs_gcc.c
|
+---.settings
| org.eclipse.cdt.codan.core.prefs
| org.eclipse.cdt.debug.core.prefs
| org.eclipse.core.resources.prefs
|
+---Debug
| | ccsObjs.opt
| | makefile
| | objects.mk
| | sources.mk
| | subdir_rules.mk
| | subdir_vars.mk
| | TM4C129EXL-FreeRTOS.map
| |
| +---driverlib
| | subdir_rules.mk
| | subdir_vars.mk
| |
| \---FreeRTOS-Kernel
| | subdir_rules.mk
| | subdir_vars.mk
| |
| \---portable
| +---GCC
| | \---ARM_CM4F
| | subdir_rules.mk
| | subdir_vars.mk
| |
| \---MemMang
| subdir_rules.mk
| subdir_vars.mk
|
+---driverlib
| adc.h
| aes.h
| can.h
| comp.h
| cpu.h
| crc.h
| debug.h
| des.h
| eeprom.h
| emac.h
| epi.h
| flash.h
| fpu.h
| gpio.h
| hibernate.h
| i2c.h
| interrupt.h
| lcd.h
| libdriver.a
| mpu.h
| onewire.h
| pin_map.h
| pwm.h
| qei.h
| rom.h
| rom_map.h
| rtos_bindings.h
| shamd5.h
| ssi.h
| sw_crc.h
| sysctl.h
| sysexc.h
| systick.h
| timer.h
| uart.h
| udma.h
| usb.h
| watchdog.h
|
+---FreeRTOS-Kernel
| | croutine.c
| | event_groups.c
| | list.c
| | queue.c
| | stream_buffer.c
| | tasks.c
| | timers.c
| |
| +---include
| | atomic.h
| | croutine.h
| | deprecated_definitions.h
| | event_groups.h
| | FreeRTOS.h
| | list.h
| | message_buffer.h
| | mpu_prototypes.h
| | mpu_wrappers.h
| | portable.h
| | projdefs.h
| | queue.h
| | semphr.h
| | StackMacros.h
| | stack_macros.h
| | stdint.readme
| | stream_buffer.h
| | task.h
| | timers.h
| |
| \---portable
| +---GCC
| | \---ARM_CM4F
| | port.c
| | portmacro.h
| |
| \---MemMang
| heap_4.c
|
\---inc
asmdefs.h
hw_adc.h
hw_aes.h
hw_can.h
hw_ccm.h
hw_comp.h
hw_des.h
hw_eeprom.h
hw_emac.h
hw_epi.h
hw_fan.h
hw_flash.h
hw_gpio.h
hw_hibernate.h
hw_i2c.h
hw_ints.h
hw_lcd.h
hw_memmap.h
hw_nvic.h
hw_onewire.h
hw_pwm.h
hw_qei.h
hw_shamd5.h
hw_ssi.h
hw_sysctl.h
hw_sysexc.h
hw_timer.h
hw_types.h
hw_uart.h
hw_udma.h
hw_usb.h
hw_watchdog.h
tm4c1294ncpdt.h
Related
I am trying to use libmm-glib documentation to put together a program to gather cellular modem information on Linux (Ubuntu 20.04). My question is how do I establish a GIOStream, and subsequently a GDBusConnection to the device. Namely, my device when pinged from the command line shows 2 tty devies, but both are labelled as "ignore" (dev/ttyUSB4,dev/ttyUSB1). I have also tried using /dev/cdc-wdm0 to initialize the Gfile with no success.
Steps (code below):
get a GFile associated with the modem
a. What path should I use to the device?
construct a GIOStream to the modem with the GFile
construct a DBusConnection with the GIOStream
contruct a MMManager with the DBusConnection
Use MMManager to query the specific modem.
gcc main.c -I/usr/include/libmm-glib -I/usr/include/ModemManager -I/usr/include/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include -lglib-2.0 -lz -lgio-2.0 -lpthread -lmm-glib
#include <libmm-glib.h>
#include <gio/gio.h>
//#include <gtk/gtk.h>
#include <stdio.h>
int main (void)
{
printf("begin 1\n");
GCancellable *cancellable;
GError **ppError;
MMManager *pManager;
GDBusAuthObserver *observer;
GDBusObjectManagerClientFlags flags = G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE;
const gchar *guid = NULL;
//g_type_init();
//GFile * save = g_file_new_for_path("/org/freedesktop/ModemManager1/Modem/3");
//GFile * save = g_file_new_for_path("/sys/devices/platform/soc#0/32c00000.bus/32e50000.usb/ci_hdrc.1/usb1/1-1/1-1.3");
GFile * save = g_file_new_for_path("/dev/ttyUSB0");
if(save == NULL)
{
printf("null GFile\n");
}
else
{
printf("GFile OK\n");
}
GFileIOStream *pStream = g_file_open_readwrite(save, NULL, NULL);
if(pStream == NULL)
{
printf("null pStream\n");
}
else
{
printf("pStream OK\n");
}
GDBusConnection *pConnection= g_dbus_connection_new_sync(pStream,
guid, // for authent. as a server
flags,
NULL, // observer,
NULL, // cancellable,
ppError);
if(pConnection == NULL)
{
printf("null GDBusConnection\n");
}
pManager = mm_manager_new_sync(pConnection,
flags,
cancellable,
ppError);
if(pManager == NULL)
{
printf("null pManager\n");
}
mm_manager_scan_devices_sync(pManager,
cancellable,
ppError);
MMObject modem;
printf("d\n");
//const gchar* pChar = mm_object_get_path(&modem);
//free resources here
printf("end\n");
return(0);
}
-----------------------------
General | path: /org/freedesktop/ModemManager1/Modem/3
| device id:
-----------------------------
Hardware | manufacturer: Telit
| model: LE910C4-NF
| firmware revision: 25.21.660 1 [Mar 04 2021 12:00:00]
| carrier config: default
| h/w revision: 1.30
| supported: gsm-umts, lte
| current: gsm-umts, lte
| equipment id:
-----------------------------
System | device: /sys/devices/platform/soc#0/32c00000.bus/32e50000.usb/ci_hdrc.1/usb1/1-1/1-1.3
| drivers: qmi_wwan, option
| plugin: telit
| primary port: cdc-wdm0
| ports: cdc-wdm0 (qmi), ttyUSB0 (ignored), ttyUSB1 (gps),
| ttyUSB4 (ignored), wwan0 (net)
-----------------------------
Status | state: failed
| failed reason: sim-missing
| power state: on
| signal quality: 0% (cached)
-----------------------------
Modes | supported: allowed: 3g; preferred: none
| allowed: 4g; preferred: none
| allowed: 3g, 4g; preferred: 4g
| allowed: 3g, 4g; preferred: 3g
| current: allowed: any; preferred: none
-----------------------------
Bands | supported: utran-4, utran-5, utran-2, eutran-2, eutran-4, eutran-5,
| eutran-12, eutran-13, eutran-14, eutran-66, eutran-71
-----------------------------
IP | supported: ipv4, ipv6, ipv4v6
-----------------------------
SIM | sim slot paths: slot 1: none (active)
| slot 2: none
I am using an Adafruit Ft232H breakout to add GPIO ports to my Linux pc. Although I had some success to flash a led with libftdi and bitbang mode, I don't have the same luck with libgpiod because gpiod_line_request_output is failing.
Some gpio information of my system:
sudo gpiodetect
gpiochip0 [ftdi-cbus] (4 lines)
sudo gpioinfo
gpiochip0 - 4 lines:
line 0: unnamed unused input active-high
line 1: unnamed unused input active-high
line 2: unnamed unused input active-high
line 3: unnamed unused input active-high
This is the C program which tries to access the line 0.
#include <stdio.h>
#include <stdlib.h>
#include <gpiod.h>
#define LINE_NUM 0
void gpio_fatal(struct gpiod_chip* chip, const char msg[20]);
int main(int argc, char** argv)
{
struct gpiod_chip* chip;
struct gpiod_line* line;
const char path[] = "/dev/gpiochip0";
chip = gpiod_chip_open(path);
if(!chip)
{
fprintf(stderr, "Error opening path\n");
return EXIT_FAILURE;
}
line = gpiod_chip_get_line(chip, LINE_NUM);
if(!line)
{
fprintf(stderr, "error getting this line\n");
return EXIT_FAILURE;
}
int ret = gpiod_line_request_output(line,
"ftdi-cbus",
1);
if(ret != 0)
gpio_fatal(chip, "Request output failed");
for(;;)
{
gpiod_line_set_value(line, 1);
printf("On\n");
sleep(1);
gpiod_line_set_value(line, 0);
printf("Off\n");
sleep(1);
}
gpiod_line_release(line);
gpiod_chip_close(chip);
return EXIT_SUCCESS;
}
void gpio_fatal(struct gpiod_chip* chip, const char* msg)
{
fprintf(stderr, "%s\n", msg);
gpiod_chip_close(chip);
exit(EXIT_FAILURE);
}
Running the executable with sudo gives me:
sudo g_gpiod/build/g_gpiod
Password:
Request output failed
gpiod.h states for the failing function the following:
/**
* #brief Reserve a single line, set the direction to output.
* #param line GPIO line object.
* #param consumer Name of the consumer.
* #param default_val Initial line value.
* #return 0 if the line was properly reserved, -1 on failure.
*/
int gpiod_line_request_output(struct gpiod_line *line,
const char *consumer, int default_val) GPIOD_API;
The parameters seem to be correct, for what reason could this be failing? Other examples using libftdi or CircuitPython can access the ports and work correctly.
You need to flash the EEPROM to set the function of pin C5, e.g. using the ftdi_eeprom command from libftdi. First, unload the ftdi_sio module and save the original EEPROM:
$ sudo rmmod ftdi_sio
$ sudo ftdi_eeprom --verbose --device i:0x0403:0x6014 ft232h-orig.conf
FTDI eeprom generator v0.17
(c) Intra2net AG and the libftdi developers <opensource#intra2net.com>
FTDI read eeprom: 0
EEPROM size: 256
VID: 0x0403
PID: 0x6014
Release: 0x0900
Bus Powered: 100 mA
Manufacturer: ÿÿÿÿÿÿÿÿ
Product: ÿÿÿÿÿÿ
Serial: ÿÿÿÿÿÿÿÿ
Checksum : ffff
PNP: 1
Channel A has Mode UART
FT1284 Mode Clock is idle LOW, MSB first, No Flow Control
ACBUS has 4 mA drive
ADBUS has 4 mA drive
C0 Function: TRISTATE
C1 Function: TRISTATE
C2 Function: TRISTATE
C3 Function: TRISTATE
C4 Function: TRISTATE
C5 Function: TRISTATE
C6 Function: TRISTATE
C7 Function: TRISTATE
C8 Function: DRIVE_1
C9 Function: DRIVE_0
FTDI close: 0
The file ft232h-orig.conf contains just a single line filename="ft232h-orig.bin".
You can control 4 GPIO pins of the FT232H using the ftdi_sio module:
| line | pin | remarks |
==========================
| 0 | C5 | - |
| 1 | C6 | - |
| 2 | C8 | red led |
| 3 | C9 | green led |
The Adafruit board has the cathodes of two LEDs (red and green) connected to pins C8 and C9. The default EEPROM has C9 set to DRIVE_0 so that the green LED is "on" when the board is powered up.
Here is my config file for ftdi_eeprom:
$ cat ft232h-libgpiod.conf
vendor_id="0x0403"
product_id="0x6014"
manufacturer="Adafruit"
product="FT232H Breakout"
# whatever
serial="20211223"
use_serial=true
max_power=100
self_powered=false
remote_wakeup=false
cha_type=UART
cha_vcp=false
cbush5=IOMODE
cbush6=IOMODE
# red led
cbush8=IOMODE
# green led
cbush9=DRIVE_0 # power-on indicator
#cbush9=IOMODE
$ sudo ftdi_eeprom --verbose --device i:0x0403:0x6014 --flash-eeprom ft232h-libgpiod.conf
Your program now works fine with line 0 on pin C5. As a bonus, you can now control the red LED with the libgpiod commands:
# turn red LED on (low active)
sudo gpioset gpiochip0 2=0
I'm investigation how different compilers handle unaligned access of structure bitfields members as well as members that cross the primitive types' boundaries, and I think MinGW64 is bugged. My test program is:
#include <stdint.h>
#include <stdio.h>
/* Structure for testing element access
The crux is the ISO C99 6.7.2.1p10 item:
An implementation may allocate any addressable storage unit large enough to hold a bitfield.
If enough space remains, a bit-field that immediately follows another bit-field in a
structure shall be packed into adjacent bits of the same unit. If insufficient space remains,
whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is
implementation-defined. The order of allocation of bit-fields within a unit (high-order to
low-order or low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified.
*/
typedef struct _my_struct
{
/* word 0 */
uint32_t first :32; /**< A whole word element */
/* word 1 */
uint32_t second :8; /**< bits 7-0 */
uint32_t third :8; /**< bits 15-8 */
uint32_t fourth :8; /**< bits 23-16 */
uint32_t fifth :8; /**< bits 31-24 */
/* word 2 */
uint32_t sixth :16; /**< bits 15-0 */
uint32_t seventh :16; /**< bits 31-16 */
/* word 3 */
uint32_t eigth :24; /**< bits 23-0 */
uint32_t ninth :8; /**< bits 31-24 */
/* word 4 */
uint32_t tenth :8; /**< bits 7-0 */
uint32_t eleventh :24; /**< bits 31-8 */
/* word 5 */
uint32_t twelfth :8; /**< bits 7-0 */
uint32_t thirteeneth :16; /**< bits 23-8 */
uint32_t fourteenth :8; /**< bits 31-24 */
/* words 6 & 7 */
uint32_t fifteenth :16; /**< bits 15-0 */
uint32_t sixteenth :8; /**< bits 23-16 */
uint32_t seventeenth :16; /**< bits 31-24 & 7-0 */
/* word 7 */
uint32_t eighteenth :24; /**< bits 31-8 */
/* word 8 */
uint32_t nineteenth :32; /**< bits 31-0 */
/* words 9 & 10 */
uint32_t twentieth :16; /**< bits 15-0 */
uint32_t twenty_first :32; /**< bits 31-16 & 15-0 */
uint32_t twenty_second :16; /**< bits 31-16 */
/* word 11 */
uint32_t twenty_third :32; /**< bits 31-0 */
} __attribute__((packed)) my_struct;
uint32_t buf[] = {
0x11223344, 0x55667788, 0x99AABBCC, 0x01020304, /* words 0 - 3 */
0x05060708, 0x090A0B0C, 0x0D0E0F10, 0x12131415, /* words 4 - 7 */
0x16171819, 0x20212324, 0x25262728, 0x29303132, /* words 8 - 11 */
0x34353637, 0x35363738, 0x39404142, 0x43454647 /* words 12 - 15 */
};
uint32_t data[64];
int main(void)
{
my_struct *p;
p = (my_struct*) buf;
data[0] = 0;
data[1] = p->first;
data[2] = p->second;
data[3] = p->third;
data[4] = p->fourth;
data[5] = p->fifth;
data[6] = p->sixth;
data[7] = p->seventh;
data[8] = p->eigth;
data[9] = p->ninth;
data[10] = p->tenth;
data[11] = p->eleventh;
data[12] = p->twelfth;
data[13] = p->thirteeneth;
data[14] = p->fourteenth;
data[15] = p->fifteenth;
data[16] = p->sixteenth;
data[17] = p->seventeenth;
data[18] = p->eighteenth;
data[19] = p->nineteenth;
data[20] = p->twentieth;
data[21] = p->twenty_first;
data[22] = p->twenty_second;
data[23] = p->twenty_third;
if( p->fifth == 0x55 )
{
data[0] = 0xCAFECAFE;
}
else
{
data[0] = 0xDEADBEEF;
}
int i;
for (i = 0; i < 24; ++i) {
printf("data[%d] = 0x%0x\n", i, data[i]);
}
return data[0];
}
And the results I found are:
| Data Member | Type | GCC Cortex M3 | GCC mingw64 | GCC Linux | GCC Cygwin |
|:------------|:-------:|:---------------|:--------------|:--------------|:--------------|
| data[0] | uint32_t| 0x0 | 0xcafecafe | 0xcafecafe | 0xcafecafe |
| data[1] | uint32_t| 0x11223344 | 0x11223344 | 0x11223344 | 0x11223344 |
| data[2] | uint32_t| 0x88 | 0x88 | 0x88 | 0x88 |
| data[3] | uint32_t| 0x77 | 0x77 | 0x77 | 0x77 |
| data[4] | uint32_t| 0x66 | 0x66 | 0x66 | 0x66 |
| data[5] | uint32_t| 0x55 | 0x55 | 0x55 | 0x55 |
| data[6] | uint32_t| 0xbbcc | 0xbbcc | 0xbbcc | 0xbbcc |
| data[7] | uint32_t| 0x99aa | 0x99aa | 0x99aa | 0x99aa |
| data[8] | uint32_t| 0x20304 | 0x20304 | 0x20304 | 0x20304 |
| data[9] | uint32_t| 0x1 | 0x1 | 0x1 | 0x1 |
| data[10] | uint32_t| 0x8 | 0x8 | 0x8 | 0x8 |
| data[11] | uint32_t| 0x50607 | 0x50607 | 0x50607 | 0x50607 |
| data[12] | uint32_t| 0xc | 0xc | 0xc | 0xc |
| data[13] | uint32_t| 0xa0b | 0xa0b | 0xa0b | 0xa0b |
| data[14] | uint32_t| 0x9 | 0x9 | 0x9 | 0x9 |
| data[15] | uint32_t| 0xf10 | 0xf10 | 0xf10 | 0xf10 |
| data[16] | uint32_t| 0xe | 0xe | 0xe | 0xe |
| data[17] | uint32_t| 0x150d | 0x1415 | 0x150d | 0x150d |
| data[18] | uint32_t| 0x121314 | 0x171819 | 0x121314 | 0x121314 |
| data[19] | uint32_t| 0x16171819 | 0x20212324 | 0x16171819 | 0x16171819 |
| data[20] | uint32_t| 0x2324 | 0x2728 | 0x2324 | 0x2324 |
| data[21] | uint32_t| 0x27282021 | 0x29303132 | 0x27282021 | 0x27282021 |
| data[22] | uint32_t| 0x2526 | 0x3637 | 0x2526 | 0x2526 |
| data[23] | uint32_t| 0x29303132 | 0x35363738 | 0x29303132 | 0x29303132 |
GCC Cortex M3 is
arm-none-eabi-gcc (GNU MCU Eclipse ARM Embedded GCC, 32-bit) 8.2.1 20181213 (release) [gcc-8-branch revision 267074]
GCC Mingw is
gcc.exe (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 8.1.0
GCC Linux is
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23)
GCC Cygwin is
gcc (GCC) 7.4.0
All GCC versions seem to correctly handle unaligned access (like my_struct.thirteeneth).
The problem is not that members who cross the word boundary (my_struct.seventeenth) are different, as the C99 standard quoted above clearly states that the behaviour is implementation-defined. The problem is that all subsequent accesses are clearly incorrect (data[17] and on) even for aligned members (my_struct.nineteenth & my_struct.twenty_third). What's going on here, is this a bug or are these valid values?
It is not bugged, it lays the bitfields according to windows ABI.
According to gcc docs:
If packed is used on a structure, or if bit-fields are used, it may be that the Microsoft ABI lays out the structure differently than the way GCC normally does.
Compile mingw64 version with -mno-ms-bitfields to fix the difference. Or compile all other versions with -mms-bitfields to lay out the structure the same as mingw.
The chances that a widely used compiler like GCC has a bug is not zero but really minimal. And odds are that PEBKAS. ;-)
Anyway, I have compiled your programm with "gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0" and got the same result as you in the column "mingw64".
A finer look reveals that the compiler aligns the bitfields on 32-bit boundaries which happens to be the width of an int. This conforms perfectly to chapter 6.7.2.1 of the standard C17 which states that the "straddling" (in its words of the annex J.3.9) is implementation-defined.
The other GCC variants are not aligning the bit fields and support crossing 32-bit boundaries.
It is clearly not a bug, the values are valid. It might be worth to research the reasons and perhaps post a feature request.
Edit:
Just to clarify, this is the layout with alignment. There is nothing wrong with elements seventeenth and following:
/* 0x11223344: word 0 */
uint32_t first :32;
/* 0x55667788: word 1 */
uint32_t second :8;
uint32_t third :8;
uint32_t fourth :8;
uint32_t fifth :8;
/* 0x99AABBCC: word 2 */
uint32_t sixth :16;
uint32_t seventh :16;
/* 0x01020304: word 3 */
uint32_t eigth :24;
uint32_t ninth :8;
/* 0x05060708: word 4 */
uint32_t tenth :8;
uint32_t eleventh :24;
/* 0x090A0B0C: word 5 */
uint32_t twelfth :8;
uint32_t thirteeneth :16;
uint32_t fourteenth :8;
/* 0x0D0E0F10: words 6 */
uint32_t fifteenth :16;
uint32_t sixteenth :8;
/* 0x12131415: word 7, because "seventeenth" does not fit in the space left */
uint32_t seventeenth :16;
/* 0x16171819: word 8, because "eighteenth" does not fit in the space left */
uint32_t eighteenth :24;
/* 0x20212324: word 9, because "nineteenth" does not fit in the space left */
uint32_t nineteenth :32;
/* 0x25262728: words 10 */
uint32_t twentieth :16;
/* 0x29303132: word 11, because "twenty_first" does not fit in the space left */
uint32_t twenty_first :32;
/* 0x34353637: word 12 */
uint32_t twenty_second :16;
/* 0x35363738: word 13, because "twenty_third" does not fit in the space left */
uint32_t twenty_third :32;
You can not rely at all, in any way, on how bit-fields are arranged in a structure.
Per 6.7.2.1 Structure and union specifiers, paragraph 11 of the C11 standard (bolding mine):
An implementation may allocate any addressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.
You even quoted that. Given that, there is no "incorrect" way for an implementation to lay out a bit-field.
So you can not rely on the size of the bit-field container.
You can not rely on whether or not a bit-field crosses units.
You can not rely on the order of bit-fields within a unit.
Yet your question assumes you can do all that, even using terms such as "correct" when you see what you expected and "clearly incorrect" to describe bit-field layouts you didn't expect.
It's not "clearly incorrect".
If you need to know where a bit is in a structure, you simply can not portably use bit-fields.
In fact, all your effort on this question is a perfect case study in why you can't rely on bit-fields.
I have got a sim900 module which has a rs232 serial port. when I connect it
to my computer it works fine on a terminal but when I connect it to an atmega16 micro controller it only echoes back what ever I send to it and does not answer to commands.
besides i use a max232 ic to convert rs232 to ttl.
#include <io.h>
#include <mega16a.h>
#include <alcd.h>
#include <delay.h>
#include <stdio.h>
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if(data!=0xd && data!= 0xa)lcd_putchar(data);
}
void main(void)
{
////////////////////////I/O REGISTERS
DDRB = 1 << DDB0;
///////////////////////USART REGISTERS
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM);
UCSRB=(1<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRH=0x00;
UBRRL=0x33;
///////////////////////ENABLE GLOBAL INTERUPTS
#asm("sei")
///////////////////////LCD CONFIGURATION
lcd_init(16);
lcd_gotoxy(0,0);
delay_ms(2000);
printf("ATE0\r\n");
delay_ms(2000);
printf("ATD+989190077175;\r\n");
delay_ms(20000);
while (1)
{
lcd_clear();
lcd_gotoxy(0,0);
// Please write your application code here
printf("AT\r\n");
delay_ms(2000);
}
}
You are obviously not talking to your SIM900.
The command "ATE0" you are issuing, is supposed to make SIM900 to switch the echo off. So, after that command you can't see echo from SIM.
Given the information you have provided I could suggest the following:
Check your max232 schematics. The easiest case here is the you have somehow Rx/Tx connected, which would explain both - you seeing the echo and not communicating with SIM. To troubleshoot that - just connect your max232 to the computer with serial terminal program and on the output side of the converter connect Rx/Tx. You should see the echo. Then disconnect them - you should not see the echo.
General suggestion - this is not the exactly the right place for such discussions. That's more Question/Answer knowledgebase.
I've been searching everywhere finding a documentation that explains when to use each flags of kmalloc. I found this reference which fairly explains when to use some of the flags but I can't find the other flags like GFP_HIGHUSER_PAGECACHE, GFP_HIGHUSER_MOVABLE and other flags in gfp.h header file... Can somebody tell me when to use these other flags?
You want section Get Free Page (GFP) Flags of Understanding the Linux Virtual Memory Manager (pdf). It is for the 2.4 kernel but it should still apply.
original post:
From the 2.6.32 gfp.h:
/*
* Action modifiers - doesn't change the zoning
*
* __GFP_REPEAT: Try hard to allocate the memory, but the allocation attempt
* _might_ fail. This depends upon the particular VM implementation.
*
* __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
* cannot handle allocation failures.
*
* __GFP_NORETRY: The VM implementation must not retry indefinitely.
*
* __GFP_MOVABLE: Flag that this page will be movable by the page migration
* mechanism or reclaimed
*/
#define __GFP_WAIT ((__force gfp_t)0x10u) /* Can wait and reschedule? */
#define __GFP_ ((__force gfp_t)0x20u) /* Should access emergency pools? */
#define __GFP_IO ((__force gfp_t)0x40u) /* Can start physical IO? */
#define __GFP_FS ((__force gfp_t)0x80u) /* Can call down to low-level FS? */
#define __GFP_COLD ((__force gfp_t)0x100u) /* Cache-cold page required */
#define __GFP_NOWARN ((__force gfp_t)0x200u) /* Suppress page allocation failure warning */
#define __GFP_REPEAT ((__force gfp_t)0x400u) /* See above */
#define __GFP_NOFAIL ((__force gfp_t)0x800u) /* See above */
#define __GFP_NORETRY ((__force gfp_t)0x1000u)/* See above */
#define __GFP_COMP ((__force gfp_t)0x4000u)/* Add compound page metadata */
#define __GFP_ZERO ((__force gfp_t)0x8000u)/* Return zeroed page on success */
#define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
#define __GFP_HARDWALL ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
#define __GFP_THISNODE ((__force gfp_t)0x40000u)/* No fallback, no policies */
#define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) /* Page is reclaimable */
Also, from kernel archives:
To make code easier to read, a set of
three GFP flags are added called
GFP_PAGECACHE, GFP_NOFS_PAGECACHE and
GFP_HIGHUSER_PAGECACHE.
Looking at the diff source on that page shows the flags you were asking about are a combination of existing flags:
#define GFP_HIGHUSER_MOVABLE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
__GFP_HARDWALL | __GFP_HIGHMEM | \
__GFP_MOVABLE)
+#define GFP_NOFS_PAGECACHE (__GFP_WAIT | __GFP_IO | __GFP_MOVABLE)
+#define GFP_USER_PAGECACHE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+ __GFP_HARDWALL | __GFP_MOVABLE)
+#define GFP_HIGHUSER_PAGECACHE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+ __GFP_HARDWALL | __GFP_HIGHMEM | \
+ __GFP_MOVABLE)
#ifdef CONFIG_NUMA
#define GFP_THISNODE (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)