Error while trying to update array element - c

I am working on an embedded platform which does not have debugging features. So it is hard to say what is the error source.
I have defined in header file:
typedef struct cm_packet {
CM_Header Header; //header of packet 3 bytes
uint8_t *Data; //packet data 64 bytes
CM_Footer Footer; //footer of packet 3 bytes
} CM_Packet;
typedef struct cm_inittypedef{
uint8_t DeviceId;
CM_Packet Packet;
} CM_InitTypeDef;
extern CM_InitTypeDef cmHandler;
void CM_Init(CM_InitTypeDef *handler);
CM_AppendResult CM_AppendData(CM_InitTypeDef *handler, uint8_t identifier
, uint8_t *data, uint8_t length);
And somewhere in implementation I have:
uint8_t bufferIndex = 0;
void CM_Init(CM_InitTypeDef *cm_initer) { //init a handler
cmHandler.DeviceId = cm_initer->DeviceId;
CM_Packet cmPacket;
cmPacket.Header.DeviceId = cm_initer->DeviceId;
cmPacket.Header.PacketStart = CM_START;
cmPacket.Footer.PacketEnd = CM_END;
//initialize data array
uint8_t emptyBuffer[CM_MAX_DATA_SIZE] = {0x00};
cmPacket.Data = emptyBuffer;
cm_initer->Packet = cmPacket;
}
CM_AppendResult CM_AppendData(CM_InitTypeDef *handler, uint8_t identifier
, uint8_t *data, uint8_t length){
//some check to see if new data does not make Data overflow
uint8_t i;
/*** ERROR HAPPENS HERE!!!! ***/
handler->Packet.Data[bufferIndex++] = identifier;
//now add the data itself
for(i = 0; i < length; i++) {
handler->Packet.Data[bufferIndex++] = data[i];
}
//reset indexer
if(bufferIndex > 64) {
PacketReady(); //mark packet as ready
bufferIndex = 0
};
//return result
}
The idea is to update the Packet.Data from some other source codes which have access to the handler. For example some other sources can call that Append function to change Packet.Data. But as you see in the code, I have commented the place which causes the micro-controller to go in hard fault mode. I am not sure what is happening here. All I know is exactly at that line micro goes into hard fault mode and never recovers!
This might be a race condition but before anything else I want to know I have written correct c !!! code then I try to rule out other problems.

In function CM_Init, you are setting cmPacket.Data to point to a local array:
uint8_t emptyBuffer[CM_MAX_DATA_SIZE] = {0x00};
cmPacket.Data = emptyBuffer;
Accessing this memory address outside the scope of the function yields undefined behavior.

As #barak manos mentioned, the buffer supplied to Data is allocated on the stack.
When you get to CM_AppendData, you are writing over memory that is no longer dedicated to the buffer.
You may want to use malloc so that the buffer is allocated on the heap instead of on the stack. Just remember to call free so that you are not leaking memory.
If you can't use dynamic allocation, it's possible to dedicate some scratch memory for all the Data uses. It just needs to be static.
Hope that helps :)

Related

need support utilizing FM_1808(F-RAM Memory) for the data extraction using structure pointers

I am working on field oriented control for PMSM. I'm using customized hardware, and unfortunetly i can't see the speed responses and current signal straight on the oscilliscope through pins. So i need to save data in FM_1808(F-RAM Memory) and then later uses FM_1808(F-RAM Memory) to plot the signals. I'm using structure to keep all data in one function with the pointer, pointing to that function. unfortunetly i can't utilized the FRAM quite well and unable to extract the data. i need help to find where i'm doing wrong that make problem in extracting the data. thanks your help will be highly appreciated. I have attached some lines of code for where i define structure, starting address and function to extract data.
define.c
#pragma DATA_SECTION(FRAMAdr,"FRAMData");
volatile struct FRAMAddress FRAMAdr;
linker cmd
page1
{
EXTFRAM : origin = 0x200000, length = 0x008000
}
Sections
{
FRAMData: > EXTFRAM PAGE = 1
}
define.h
struct FRAMAddress {
int16 Dat[32768]; // FRAM 16bit data & 16bit memory
};
extern volatile struct FRAMAddress FRAMAdr;
Uint16 *FRAMStartAdr = (Uint16 *)0x200000;
pheripheral.c
void FSave(Uint16 FAdr, int16 FD1, int16 FD2)
{
FRamAdr.Dat[FAdr] = FD1;
DELAY_US(0.2L);
FRamAdr.Dat[FAdr+5000] = FD2;
}
main.c
extern void FSave(Uint16 FAdr1, int16 FD1, int16 FD2);
{
if(FIndex<=5000)
{
FSave(FIndex, (int16)spd, (int16)(id));
FIndex++;
}
else
{
FSaveflag=0;
}
}
i would like to seek help regarding data value at memory addresses using FM_1808(F-RAM Memory).
I suspect you probably want something like this, assuming your FRAM is mapped at address 0x200000.
struct FRAM {
uint16_t Dat[32768];
};
struct FRAM * FRAMData = (struct FRAM *)0x200000;
void FSave(Uint16 FAdr, int16 FD1, int16 FD2)
{
FRAMData->Dat[FAdr] = FD1;
DELAY_US(0.2L);
FRAMData->Dat[FAdr+5000] = FD2;
}
Note that the datasheet I found online suggests the FM1808 has 32K 8-bit values, not 16-bit values, so you should look into that.
Edit: Also not sure your delay is needed or makes sense. What is the type of 0.2L? What parameter type does DELAY_US() take?

AT91 ARM EMAC polling issue

I am using atmel's lwip example. Interfacing with PHY is ok. It can link and even auto negotiate. Netif is going up. But when i start polling netif nothing happens. Ive narrowed down problem to EMAC_Poll
unsigned char EMAC_Poll(unsigned char *pFrame, unsigned int frameSize, unsigned int *pRcvSize)
{
unsigned short bufferLength;
unsigned int tmpFrameSize=0;
unsigned char *pTmpFrame=0;
unsigned int tmpIdx = rxTd.idx;
volatile EmacRxTDescriptor *pRxTd = rxTd.td + rxTd.idx;
ASSERT(pFrame, "F: EMAC_Poll\n\r");
char isFrame = 0;
// Set the default return value
*pRcvSize = 0;
// Process received RxTd
while ((pRxTd->addr & EMAC_RX_OWNERSHIP_BIT) == EMAC_RX_OWNERSHIP_BIT) {
// Never got there.
...
}
return EMAC_RX_NO_DATA;
}
typedef struct {
volatile EmacRxTDescriptor td[RX_BUFFERS];
EMAC_RxCallback rxCb; /// Callback function to be invoked once a frame has been received
unsigned short idx;
} RxTd;
/// Describes the type and attribute of Receive Transfer descriptor.
typedef struct _EmacRxTDescriptor {
unsigned int addr;
unsigned int status;
} __attribute__((packed, aligned(8))) EmacRxTDescriptor, *PEmacRxTDescriptor;
There is while loop, but condition is never goes true.
I have very vague presentation what is RxTd and what exacly this condition means. However i can not see how thise RxTd Would change to pass condition. All references of RxTd leads to same emac.c module. Most of them in that polling function and rest in EMAC_ResetRx function.
static void EMAC_ResetRx(void)
{
unsigned int Index;
unsigned int Address;
// Disable RX
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_RE;
// Setup the RX descriptors.
rxTd.idx = 0;
for(Index = 0; Index < RX_BUFFERS; Index++) {
Address = (unsigned int)(&(pRxBuffer[Index * EMAC_RX_UNITSIZE]));
// Remove EMAC_RX_OWNERSHIP_BIT and EMAC_RX_WRAP_BIT
rxTd.td[Index].addr = Address & EMAC_ADDRESS_MASK;
rxTd.td[Index].status = 0;
}
rxTd.td[RX_BUFFERS - 1].addr |= EMAC_RX_WRAP_BIT;
// Receive Buffer Queue Pointer Register
AT91C_BASE_EMAC->EMAC_RBQP = (unsigned int) (rxTd.td);
}
I do not realy understand last line, but it looks like that rxTd is auto filled with AT91 itself. If it is so, there may be packing/aligment problem, but Atmel added __attribute__ ((packed, aligned(8))) on RxTd structure definition. Any way, can someone describe mechanism of data input or tell me where proble might be?
By the way i am using gcc, if that matters.
UPD:
Ive checked RSR and notice that it is start with 0, then goes to 2 after second. 2- means new data was captured.
UPD:
So i've read about function of emac in datasheet for my chip. I was right. That RBQP register must point to array of descriptors. Each descriptor consists of address and status field. The datasheet states that "bit zero of address field is written to one to show the buffer has been used". Then ARM uses another rx descriptor from that array. I guess by "has been used" they mean that that buffer is filled with frame data and ready to be processed. This must mean that data just not going to that buffer. But it must be there because REC goes high. Additionaly i've checked that RE in NCR is up and MI is enabled. I have no idea what is wrong.
I've spend whole week to solve it. The funny thing is that if i've dump memory and looked at all those addresses - The data was there whole time! So the key was to disable I and D caching and MMU itself. Hope it will help someone.

Adding flash before erasing and writing into flash

In a program to erase and write into flash, I donot understand the lines
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
struct target_flash *f = &kf->f;
from the below section of the code. And the whole program can be found at https://github.com/blacksphere/blackmagic/blob/master/src/target/kinetis.c
struct kinetis_flash {
struct target_flash f;
uint8_t write_len;
};
static void kl_gen_add_flash(target *t, uint32_t addr, size_t length,
size_t erasesize, size_t write_len)
{
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
struct target_flash *f = &kf->f;
f->start = addr;
f->length = length;
f->blocksize = erasesize;
f->erase = kl_gen_flash_erase;
f->write = kl_gen_flash_write;
f->done = kl_gen_flash_done;
f->erased = 0xff;
kf->write_len = write_len;
target_add_flash(t, f);
}
It would be great if someone helps me understanding above tw lines, thanks in advance.Many targets for example KL25, K22, K64 can be accordingly used what i understood from the project. Are those two lines storing target specific specifications for flash?
In general we donot need to allocate any space for flash right using calloc or malloc like we do it for RAM.
The code in question extends GDB, allowing it to use various JTAG or Serial Wire interfaces to program and debug certain ARM devices. Identifying the attached devices flash device is a time consuming and disruptive (as-in can't run device code) task, so you only want to do it once, hence the local RAM allocation for storing the type and current state of the attached flash.
This line
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
is a dynamic allocation of a struct kinetis_flash somewhere in RAM. It's probably used for holding information about a flash device present in the system.
This line
struct target_flash *f = &kf->f;
makes f point to the struct target_flash - named f - inside struct kinetis_flash so that you can write to it using f->some_var = ...
So the whole function is simply creating and initializing an object of type struct kinetis_flash
Though the code is correct, it's (IMO) a bit confusing to have a variable f pointing to f inside a struct. Perhaps a name like ptr_f would be more clear.
Also notice that the code is equivalent to:
static void kl_gen_add_flash(target *t, uint32_t addr, size_t length,
size_t erasesize, size_t write_len)
{
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
kf->f.start = addr;
kf->f.length = length;
...
}

Initializing, constructing and converting struct to byte array causes misalignment

I am trying to design a data structure (I have made it much shorter to save space here but I think you get the idea) to be used for byte level communication:
/* PACKET.H */
#define CM_HEADER_SIZE 3
#define CM_DATA_SIZE 16
#define CM_FOOTER_SIZE 3
#define CM_PACKET_SIZE (CM_HEADER_SIZE + CM_DATA_SIZE + CM_FOOTER_SIZE)
// + some other definitions
typedef struct cm_header{
uint8_t PacketStart; //Start Indicator 0x5B [
uint8_t DeviceId; //ID Of the device which is sending
uint8_t PacketType;
} CM_Header;
typedef struct cm_footer {
uint16_t DataCrc; //CRC of the 'Data' part of CM_Packet
uint8_t PacketEnd; //should be 0X5D or ]
} CM_Footer;
//Here I am trying to conver a few u8[4] tp u32 (4*u32 = 16 byte, hence data size)
typedef struct cm_data {
union {
struct{
uint8_t Value_0_0:2;
uint8_t Value_0_1:2;
uint8_t Value_0_2:2;
uint8_t Value_0_3:2;
};
uint32_t Value_0;
};
//same thing for Value_1, 2 and 3
} CM_Data;
typedef struct cm_packet {
CM_Header Header;
CM_Data Data;
CM_Footer Footer;
} CM_Packet;
typedef struct cm_inittypedef{
uint8_t DeviceId;
CM_Packet Packet;
} CM_InitTypeDef;
typedef struct cm_appendresult{
uint8_t Result;
uint8_t Reason;
} CM_AppendResult;
extern CM_InitTypeDef cmHandler;
The goal here is to make reliable structure for transmitting data over USB interface. At the end the CM_Packet should be converted to an uint8_t array and be given to data transmit register of an mcu (stm32).
In the main.c file I try to init the structure as well as some other stuff related to this packet:
/* MAIN.C */
uint8_t packet[CM_PACKET_SIZE];
int main(void) {
//use the extern defined in packet.h to init the struct
cmHandler.DeviceId = 0x01; //assign device id
CM_Init(&cmHandler); //construct the handler
//rest of stuff
while(1) {
CM_GetPacket(&cmHandler, (uint8_t*)packet);
CDC_Transmit_FS(&packet, CM_PACKET_SIZE);
}
}
And here is the implementation of packet.h which screws up everything so bad. I added the packet[CM_PACKET_SIZE] to watch but it is like it is just being generated randomly. Sometimes by pure luck I can see in this array some of the values that I am interested in! but it is like 1% of the time!
/* PACKET.C */
CM_InitTypeDef cmHandler;
void CM_Init(CM_InitTypeDef *cm_initer) {
cmHandler.DeviceId = cm_initer->DeviceId;
static CM_Packet cmPacket;
cmPacket.Header.DeviceId = cm_initer->DeviceId;
cmPacket.Header.PacketStart = CM_START;
cmPacket.Footer.PacketEnd = CM_END;
cm_initer->Packet = cmPacket;
}
CM_AppendResult CM_AppendData(CM_InitTypeDef *handler, uint8_t identifier,
uint8_t *data){
CM_AppendResult result;
switch(identifier){
case CM_VALUE_0:
handler->Packet.Data.Value_0_0 = data[0];
handler->Packet.Data.Value_0_1 = data[1];
handler->Packet.Data.Value_0_2 = data[2];
handler->Packet.Data.Value_0_3 = data[3];
break;
//Also cases for CM_VALUE_0, 1 , 2
//to build up the CM_Data sturct of CM_Packet
default:
result.Result = CM_APPEND_FAILURE;
result.Reason = CM_APPEND_CASE_ERROR;
return result;
break;
}
result.Result = CM_APPEND_SUCCESS;
result.Reason = 0x00;
return result;
}
void CM_GetPacket(CM_InitTypeDef *handler, uint8_t *packet){
//copy the whole struct in the given buffer and later send it to USB host
memcpy(packet, &handler->Packet, sizeof(CM_PACKET_SIZE));
}
So, the problem is this code gives me 99% of the time random stuff. It never has the CM_START which is the start indicator of packet to the value I want to. But most of the time it has the CM_END byte correctly! I got really confused and cant find out the reason. Being working on an embedded platform which is hard to debugg I am kind of lost here...
If you transfer data to another (different) architecture, do not just pass a structure as a blob. That is the way to hell: endianess, alignment, padding bytes, etc. all can (and likely will) cause trouble.
Better serialize the struct in a conforming way, possily using some interpreted control stream so you do not have to write every field out manually. (But still use standard functions to generate that stream).
Some areas of potential or likely trouble:
CM_Footer: The second field might very well start at a 32 or 64 bit boundary, so the preceeding field will be followed by padding. Also, the end of that struct is very likely to be padded by at least 1 bytes on a 32 bit architecture to allow for proper alignment if used in an array (the compiler does not care you if you actually need this). It might even be 8 byte aligned.
CM_Header: Here you likely (not guaranteed) get one uint8_t with 4*2 bits with the ordering not standardized. The field my be followed by 3 unused bytes which are required for the uint32_t interprettion of the union.
How do you guarantee the same endianess (for >uint8_t: high byte first or low byte first?) for host and target?
In general, the structs/unions need not have the same layout for host and target. Even if the same compiler is used, their ABIs may differ, etc. Even if it is the same CPU, there might be other system constraints. Also, for some CPUs, different ABIs (application binary interface) exist.

C/STM32 structure pointer

I've been working with stm32f103, now I'm trying to lunch some codes on stm32f407.
To communicate through USART interface I use fifo query in form of structure, defined in header file:
#define FIFO_BUF_SIZE 128
typedef struct {
char data[FIFO_BUF_SIZE];
uint16_t startIndex;
uint16_t endIndex;
}FIFO, *ptrFIFO;
Global declaration of this structure in source file:
FIFO RX_Buff={{},0,0};
FIFO TX_Buff={{},0,0};
Now I want to put data from char array to fifo query:
void USART_PrintData(USART_TypeDef * USART, char str[]){
ptrFIFO pTX = &TX_Buff;
int i=0;
while(str[i]!='\0'){
FIFO_Put(pTX, str[i]);
i++;
}
//here in working program is code for sending data
//deleted from program for tests
}
void FIFO_Put(ptrFIFO fifo, char data){
uint16_t tmp;
tmp = fifo->startIndex;
fifo->data[tmp]=data;
tmp = (tmp+1)%(FIFO_BUF_SIZE-1);
fifo->startIndex=tmp;
}
This code has been worked on stm32f103 but won't on f407. After last sign passed to FIFO_Put() and write to fifo query, programm go to Default_Handler or strange address in memory (depends of humor), but when I using this structure directly it works fine:
void FIFO_Put(char data){
uint16_t tmp;
tmp = TX_Buff.startIndex;
TX_Buff.data[tmp]=data;
tmp = (tmp+1)%(FIFO_BUF_SIZE-1);
TX_Buff.startIndex=tmp;
}
I have no idea what's wrong.
Thanks for any help.
I've tried to debug, and the problem is in last line in function FIFO_Put():
fifo->startIndex=tmp;
When function putting last sign to fifo, after last line program jump to default_handler.
If I comment this line, program works fine.
Check the program stack size - from my experience, such kind of undefined behavior may be caused by stack overflow.

Resources