Write to FRAM Memory Location in MSP430 - c

I am working with MSP430 with FRAM Controller. And I Have to write a data from buffer over FRAM Location.
I have gone through bundled example of writing to FRAM.
unsigned long *FRAM_write_ptr;
unsigned long data;
#define FRAM_TEST_START 0xD000
data = 0x00010001;
void main
{
while(1)
{
data += 0x00010001;
FRAM_write_ptr = (unsigned long *)FRAM_TEST_START;
FRAMWrite(); // Endless loop
count++;
if (count > 100)
{
P1OUT ^= 0x01; // Toggle LED to show 512K bytes
count = 0; // ..have been written
data = 0x00010001;
}
}
}
void FRAMWrite(void)
{
unsigned int i=0;
for ( i= 0; i<128; i++)
{
*FRAM_write_ptr++ = data;
}
}
But When I tested example, It goes beyond the FRAM allocated section.
Is there any other method for writing on to FRAM.?

Related

Writing array to flash which is uint16_t. I am using a STM32L053 nucleo., get a hard fault error. How to convert uint16_t array to write to flash?

This is the how I'm trying to write to flash
Basically I pass my uint16_t array to a function called FLASH_WriteA which accepts the array, the destination array or the location and the length
void FLASH_WriteA(uint16_t * src, uint16_t * dest, uint16_t length_16)
{
uint32_t firstAddress= FLASH_GetFirstAddress((uint32_t)dest, PAGE_SIZE_BYTES); // gets the first address of that page
uint32_t offset = ((uint32_t)dest - seg) / 2; // offset is in words
HAL_FLASH_Unlock();
Flash_Erase_Page((uint16_t*)seg); // calls the page erase function
FLASH_Write_HAL((uint32_t *)&flashBuffer, (uint16_t*)seg, FLASH_TABLE_SIZE_BYTES); //FLASH_TABLE_SIZE_BYTES = 256 = size of array
HAL_FLASH_Lock();
}
HAL_StatusTypeDef Flash_Erase_Page(uint16_t* seg){//, uint16_t length){
//uint16_t pages = (length/page_size) + (int)((length % page_size) != 0);
uint32_t pages = 2; // page size for STM32L053 = 128 bytes
FLASH_EraseInitTypeDef EraseInitStruct;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = seg;
EraseInitStruct.NbPages = pages;
uint32_t PageError;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK) //Erase the Page Before a Write Operation
{
return HAL_ERROR;
}
}
void FLASH_Write_HAL(uint32_t *p_source, uint16_t* seg, uint16_t length)
{
uint32_t varToPass;
uint16_t wordcount=0;
int i;
for (i=0; i<length; i++){
varToPass = p_source[i] ;
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,seg+wordcount,varToPass);
wordcount += 4;
// if (wordcount>=256){
// break;
// }
}
}

Can't pass array stored in .h file to C function

I am trying to implement a driver for a sensor(ST-VL53L5CX) on an AVR MCU (AVR128DB48).
The driver comes prewritten, with a few I2C functions for the user to fill in
(So the sensor can be implemented on different platforms).
The driver is made up of multiple c files. API.c, API.h, Buffers.h, Platform.c and Platform.h.
The firmware for the sensor is stored in the Buffers.h file as an array. e.g:
const uint8_t Sensor_Firmware[] = {0x05,...,0x01};
This needs to be written to the sensor.
To do this, I call a function I have written to write multiple bytes to the I2C line:
uint8_t WrMulti(VL53L5CX_Platform *p_platform,uint16_t
RegisterAdress,uint8_t *p_values,uint32_t size)
{
uint8_t count = 0;
uint32_t new_size = size + 2;
//Split Register address into 2 bytes
uint8_t temp0 = (uint8_t)((RegisterAdress & 0xFF00)>> 8);
uint8_t temp1 = (uint8_t)(RegisterAdress & 0x00FF);
//Create new array to hold Register Address and p_values
uint8_t temp_array[new_size] ;
for (int i = 0; i <new_size; i++)
{
temp_array[i] = 0;
}
//Fill temp_array with register address and p_values
temp_array[0] = temp0;
temp_array[1] = temp1;
for (int i = 2; i < (new_size); i++ )
{
temp_array[i] = p_values[count];
count++;
}
//I2C
uint8_t status = 255;
while(!I2C0_Open(p_platform->address)); // sit here until we get the bus..
I2C0_SetBuffer(temp_array,new_size);
I2C0_SetAddressNackCallback(I2C0_SetRestartWriteCallback,NULL); //NACK polling?
I2C0_MasterWrite();
while(I2C0_BUSY == I2C0_Close()); // sit here until finished.
/* This function returns 0 if OK */
status = 0;
return status;
}
This works when sending an array that is located in my main.c file.
e.g:
//buffer.h
const uint8_t Sensor_Firmware[] = {0x05,...,0x01};
//End buffer.h
.
//main.c
void main (void)
{
uint8_t I2C_address = 0x01;
uint8_t I2C_reg = 0x01;
uint32_t size = 16;
uint8_t temp_array[size];
for (int i = 0; i <size; i++)
{
temp_array[i] = Sensor_Firmware[i];
}
WrMulti(I2C_address, I2C_reg, &temp_array[0], size);
While(1)
{
;
}
}
//End main.c
It also work when passing an array from the .h file without the 'const' key word.
e.g:
//buffer.h
uint8_t Sensor_Firmware[] = {0x05,...,0x01};
//End buffer.h
.
//main.c
void main (void)
{
uint8_t I2C_address = 0x01;
uint8_t I2C_reg = 0x01;
uint32_t size = 16;
uint8_t temp_array[size];
WrMulti(I2C_address, I2C_reg, &Sensor_Firmware[0], size);
While(1)
{
;
}
}
//End main.c
It does not when I pass the 'Sensor_Firmwware[]' array (with the const key word) from the .h file to 'WrMulti'. It just ends up sending '0x00' for every byte that comes from 'Sensor_Firmware'.
Does anyone know why this is might be?
Kind regards

Weird correlation between I2C Transfer and Array size

So... i don't even know how to explain this...
I have a cc1310 Launchpad XL and a tiny EEPROM. My task is to write a library for easy transferring. In Code Composer Studio I'm using an Example project from TI with TIRTOS to test my functions. The weird thing is:
when i am declaring a uint8_t array larger than 304. my Transactions wont work. Itll only send 1 Byte and freezes.
Under 305, everything is fine.
Oh and im not even using the array. It just has to exist and nothing works.
void *mainThread(void *arg0)
{
uint32_t *pAddress;
int i;
uint8_t dat = 0;
uint32_t address = 0x00FEAA;
uint8_t data[305] = {0};
uint32_t datalen = sizeof(data);
for(i=0; i< 305; i++)
{
data[i]=dat;
dat++;
}
pAddress=&address;
int write = EEPROM_sWrite(pAddress, data,datalen);
return 0;
}
and
int EEPROM_sWrite(uint32_t *address, uint8_t *data, uint32_t datalen)
{
I2C_init();
//needed variables and initialization
uint8_t writebuf[258] = {0};
uint8_t blocksize = 0;
uint8_t *p = &writebuf[2];
if((*address+datalen)>maxAddress) //out of bounds?
{
return 1;
}
else
{
I2C_Transaction Transaction = {0};
Transaction.slaveAddress = slaveAddressA;
Transaction.writeBuf = writebuf;
Transaction.writeCount = blocksize;
Transaction.readBuf = NULL;
Transaction.readCount =0;
I2C_Params params;
I2C_Params_init(&params);
params.bitRate = I2C_400kHz;
params.transferMode = I2C_MODE_BLOCKING;
I2C_Handle Handle = I2C_open(0,&params );
//first block
if(*address>0xFFFF) //second half of the memory?
{
Transaction.slaveAddress = slaveAddressB;
}
blocksize = maxPagesize - (*address & 0xFF)+1;
//blocksize needs to be adjusted to the page size
writebuf[0] = (*address & 0xFF00) >> 8; //page address
writebuf[1] = (*address & 0xFF); //cell Address
if(datalen<=blocksize) //if it fits in a single page, just do it
{
memcpy(p,data,datalen);
//copies data to buffer (fills only needed cells in page)
Transaction.writeCount = datalen+2;
if(I2C_transfer(Handle, &Transaction))
{
I2C_close(Handle);
return 0;
}
else
{
I2C_close(Handle);
return 1;
}
}
memcpy(p,data,blocksize);//copies data to buffer (fills complete page)
Transaction.writeCount = blocksize+2;
if(!I2C_transfer(Handle, &Transaction))
{
I2C_close(Handle);
return 1;
}
usleep(10000);
//loop preparation
data+=blocksize;//shifts pointer forward
datalen-=blocksize; //reduces blocksize
writebuf[0]++; //next page
writebuf[1] = 0; //start cell is now 0 each time
//nth block
while(datalen>maxPagesize) //cut down to page sized blocks and write it down
{
//copy 256 bytes of data to buffer
memcpy(p,data,maxPagesize);
//send it
Transaction.writeCount = maxPagesize+2;
if(!I2C_transfer(Handle, &Transaction))
{
I2C_close(Handle);
return 1;
}
usleep(10000);
//preparation
data+=maxPagesize;
datalen-=maxPagesize;
//checks if it exceeds the first memory half
if(writebuf[0]==0xff)
{
Transaction.slaveAddress=slaveAddressB;
writebuf[0]=0;
}
else
{
writebuf[0]++; //next page
}
}
//last block
//copy last data
memcpy(p,data,datalen);
//send it
Transaction.writeCount = datalen+2;
if(!I2C_transfer(Handle, &Transaction))
{
I2C_close(Handle);
return 1;
}
I2C_close(Handle);
return 0;
}
}
edit:
#define maxAddress 0x1FFFF
#define maxPagesize 0xFF
forgot them..
A Reddit user had the right idea!
Turns out it was a simple stack overflow.
The Stack size of the thread was 1024. As i changed it to 2048, everything works.

STM32F4Discovery - SDCard sector reading

long time I try to implement FatFs module, but its gets crazy after every sd card formatting. (different errors each time). I've decided to go lower and check my SDCard drivers and I've noticed that when I read some (but ALWAYS THE SAME) of sector's field I receive garbage and I can't interpret it.
My driver's test looks like below:
#if 1 //SD Card Test
uint16_t i;
uint8_t CSD; //card capacity
uint8_t CID; //card id
uint8_t Buffer[512]; //this buffer is written to card
for(i=0; i<512;i++)
{
Buffer[i]=i;
}
SD_CardInit(); //card initialization
CSD = SD_Read_CSD(); //read capacity
CID = SD_Read_CSD(); //read ID
SD_WriteBlock(0x200, Buffer, 512); //write Buffer under 0x200 (512) address
SD_Read_Block(0x200); //read buffer from 0x200
CSD = 0;
#endif
I put breakpoint at CSD = 0; line. Here is what I get after writing and reading the same address:
Buffer is filled with numbers from 0 to 255 (two times, because of overflow).
To reduce noise I've minimized SPI frequency to minimum. Nothing changed. But in fact that wrong numbers appears ALWAYS under the same table index and with the same values suggest that is no problem with noise, but some error.
It looks like drivers works properly, because they write and read most of the fields, but always in the same it answer with garbage. I can't find any trace what could I do wrong. Do I write under some permitted address? When I read any random address I receive the same result.
I include functions: read and write (SD_Sector is a global buffer)
WRITE
// Write block of data to the SD card
// input:
// addr - start address of the block (must be power of two)
// pBuf - pointer to the buffer with data
// len - buffer length
// return: SDR_xxx
SDResult_TypeDef SD_WriteBlock(uint32_t addr, uint8_t *pBuf, uint32_t len)
{
uint32_t wait;
uint16_t CRC_loc; // Calculated CRC16 of the block
uint16_t i;
uint8_t cmdres, response, temp;
SDCard_privChipSelect();
// Calculate 16-bit CRC
CRC_loc = CRC16_buf(pBuf,len);
// SDSC card uses byte unit address and
// SDHC/SDXC cards use block unit address (1 unit = 512 bytes)
// For SDHC/SDXC card addr must be converted to block address
#if 0 //TODO: reconsider PiechotM, do not work with that line
if (SD_CardType == SD_HIGH_CAPACITY_SD_CARD) addr >>= 9;
#endif
response = SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK,addr); // CMD24
if (response != 0x00)
{
// Something wrong happened, do nothing
return response; // SD_CMD_READ_SINGLE_BLOCK command returns bad response
}
else
{
wait = 0; response = 0;
while (++wait <= 512/*0x1ff*/ && response == 0xff)
{
temp = 0xFF;
SD_Send( temp );
response = SD_Recv();
}
if (wait >= 0x1ff) return 0xff;
// Send start block token
SD_Send(SD_TOKEN_START_BLOCK);
// Send data block
for (i = 0; i < len; i++)
{
uint8_t temp;
SD_Send( *pBuf++ );
}
// Send CRC
SD_Send(CRC_loc >> 8);
SD_Send((uint8_t)CRC_loc);
}
// Get response from the SD card
cmdres = SD_Recv();
cmdres &= 0x1f;
if (cmdres != SD_TOKEN_DATA_ACCEPTED)
{
// Data block rejected by SD card for some reason
// Release SD card
SD_Send(0xff);
SDCard_privChipDeSelect();
if (cmdres & SD_TOKEN_WRITE_CRC_ERROR) return SDR_WriteCRCError;
if (cmdres & SD_TOKEN_WRITE_ERROR) return SDR_WriteErrorInternal;
return SDR_WriteError;
}
// Wait while the SD card is busy by data programming
wait = 0x7fff; // Recommended timeout is 250ms (500ms for SDXC)
do
{
cmdres = SD_Recv();
} while (cmdres == 0 && --wait);
// Provide extra 8 clocks for the card (from SanDisk specification)
SD_Send(0xff);
// Release SD card
SDCard_privChipDeSelect();
// Must send at least 74 clock ticks to SD Card
for (wait = 0; wait < 10; wait++) SD_Send(0xff);
return SDR_Success;
}
READ
// return:
// 0x00 -- read OK
// 0x01..0xfe -- error response from CMD17
// 0xff -- timeout
uint8_t SD_Read_Block(uint32_t addr)
{
uint32_t wait;
uint16_t i;
uint8_t response;
SDCard_privChipSelect();
#if 0 //TODO: reconsider PiechotM, do not work with that line
if (SD_CardType != SD_HIGH_CAPACITY_SD_CARD) addr <<= 9; // Convert block number to byte offset
#endif
response = SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK,addr); // CMD17
if (response != 0x00)
{
// Something wrong happened, fill buffer with zeroes
for (i = 0; i < 512; i++) SD_sector[i] = 0;
return response; // SD_CMD_READ_SINGLE_BLOCK command returns bad response
}
else
{
wait = 0; response = 0;
while (++wait <= 0x1ff && response != 0xfe) response = SD_Recv();
if (wait >= 0x1ff) return 0xff;
// Read 512 bytes of sector
for (i = 0; i < 512; i++) SD_sector[i] = SD_Recv();
}
// Receive 16-bit CRC (some cards demand this)
SD_CRC16_rcv = SD_Recv() << 8;
SD_CRC16_rcv |= SD_Recv();
// Calculate CRC16 of received buffer
SD_CRC16_cmp = CRC16_buf(&SD_sector[0],512);
SDCard_privChipDeSelect();
// Must send at least 74 clock ticks to SD Card
for (wait = 0; wait < 8; wait++) SD_Send(0xff);
return 0;
}
/* -------------------- WRITE SECTION ------------------------------*/
/* Lonely Wolf library imported */
/*------------------------PiechotM----------------------------------*/
// Send buffer to the SD card
// input:
// pBuf - pointer to the buffer
// len - length of the buffer
// return: last response from SD card
void SD_WriteBuf(uint8_t *pBuf, uint16_t len)
{
while (len--) SD_Send(*pBuf++);
}
I will be very thankful for your help!
Best regards,
Maks Piechota

typecasting char variable into unsigned int

I am trying to convert char variables into Unsigned int. my code is
char spi(char data)
{
//Start transmision
SPDR = data;
//Wait for transmision complete
while(!(SPSR & 0x80));
return SPDR;
}
unsigned int ReadAd(void)
{
unsigned int data;
ChipSelectAd(1);
//Read data
CheckStatus();
spi(0x58);
data = (spi(0xFF)<< 8);
data |= spi(0xFF);
return data;
}
Actually my problem is The spi function return an 8bit char so the above code shifts left 8bits the char variable and then assigns it to a 16bit variable, the result will always be 0.
In order to actually shift the data to the left I need to typecast them first to a 16bit type variable. I have tried like this
char spi(char data)
{
//Start transmision
SPDR = data;
//Wait for transmision complete
while(!(SPSR & 0x80));
return SPDR;
}
unsigned int ReadAd(void)
{
unsigned int data;
ChipSelectAd(1);
//Read data
CheckStatus();
spi(0x58);
data = (unsigned int)((unsigned char)spi(0xFF)<< 8);
data |= (unsigned int)((unsigned char)spi(0xFF));
return data;
}
void CheckStatus(void)
{
//char adcStatus;
adcStatus = 0xFF;
//Read status
while(!(adcStatus & 0x80))
{
spi(0x40);
adcStatus = spi(0xFF);
}
}
void ChipSelectAd(char s)
{
if(s == 1){
PORTB.3 = 0; //Switch on ADC
//while(PINB.3); //Wait for chip select pin
}
else
PORTB.3 = 1; //Switch off ADC
}
its not working. please suggest me which function i have to use.
Thanks in advance.
Your problem is not the casts. It works the same without them, due to the integral promotion rules.
#include <stdio.h>
char spi ( char data )
{
char SPDR = data;
return SPDR;
}
unsigned int ReadAd ( void )
{
unsigned int data;
data = spi ( 0x81 ) << 8;
data |= spi ( 0x42 );
return data;
}
int main ( void )
{
printf ( "Result %x\n", ReadAd() );
return 0;
}
This outputs Result ffff8142 on a system where char is a signed type. To get to the real problem, try assinging the values of spi() calls to variables and then print their values. Please also show us the declaration/definition of SPDR.
1) in embedded systems: get rid of the standard integer types, the default char type in particular. If you have a modern compiler, use uint8_t, uint16_t etc from stdint.h. If you have an ancient compiler, then typedef unsigned char uint8_t and so on. If you aren't using unsigned types of known size in embedded systems, you are asking for bugs bugs bugs.
2) Learn and understand integer promotion rules. It is frightening how many programmers there are that don't know about them or understand them.
Once you have the two above fundamentals sorted out, your code should look something like this code:
(I took the liberty to fix various suspicious, possible bugs and the crappy, inconsistent indention. Plus some style nitpicks.)
#include <stdint.h>
uint8_t spi (uint8_t data)
{
SPDR = data; //Start transmision
while((SPSR & 0x80) > 0) //Wait for transmision complete
;
return SPDR;
}
uint16_t ReadAd(void)
{
uint16_t data;
ChipSelectAd(true);
CheckStatus(); //Read data
(void) spi(0x58);
data = ((uint16_t)spi(0xFF)) << 8;
data |= (uint16_t)spi(0xFF);
return data;
}
void CheckStatus(void)
{
uint8_t adcStatus;
do
{
(void) spi(0x40);
adcStatus = spi(0xFF);
} while((adcStatus & 0x80) > 0);
}
void ChipSelectAd(bool on)
{
if(on)
{
PORTB.3 = 0; //Switch on ADC
}
else
{
PORTB.3 = 1; //Switch off ADC
}
}

Resources