I am working on the STM32F7xxx microcontroller. I am quite new to the entire microcontroller programming. I am using the latest STM32F7xxx libraries to build my code. I am using this microcontroller for a SLAM application. Since it doesn't have enough memory I want to save the pose information of the robot in the SDRAM. I use the libraries available at : http://stm32f4-discovery.com/2015/07/hal-library-11-sdram-for-stm32fxxx/
The code to write a float value to the SDRAM is quite simple, just a line:
#define TM_SDRAM_WriteFloat(address, value) (*(__IO float *) (SDRAM_START_ADR + (address)) = (value))
My code where I use it is as following:
void write_Landmark()
{
int address = uwIndex_lm;
SDRAM_Write8(LANDMARK_START_ADR+address,lm_head->landmark_index);
address = address +1;
SDRAM_WriteFloat(LANDMARK_START_ADR+address,lm_head->pos_x);
address = address +4;
SDRAM_WriteFloat(LANDMARK_START_ADR+address,lm_head->pos_y);
address = address +4;
SDRAM_WriteFloat(LANDMARK_START_ADR+address,lm_head->pos_theta);
address = address +4;
SDRAM_Write16(LANDMARK_START_ADR+address,lm_head->jump_point);
address = address +2;
SDRAM_Write8(LANDMARK_START_ADR+address,lm_head->landmark_detected);
address = address +1;
SDRAM_Write8(LANDMARK_START_ADR+address,lm_head->landmark_corrected);
address = address +1;
SDRAM_WriteFloat(LANDMARK_START_ADR+address,lm_head->hall_angle);
address = address +4;
SDRAM_WriteFloat(LANDMARK_START_ADR+address,lm_head->hall_distance);
address = address +4;
SDRAM_Write8(LANDMARK_START_ADR+address,lm_head->on_curve);
address = address +1;
uwIndex_lm = address;
}
The code execution gets stuck at the line where I write float to SDRAM. But if instead of
SDRAM_WriteFloat(LANDMARK_START_ADR+address,lm_head->pos_x);
I write,
SDRAM_Write32(LANDMARK_START_ADR+address,lm_head->pos_x);
it works fine. I do understand that I am getting a hard fault here, but I don't really get how to fix this.Any suggestions will be very helpful. Thanks
I just realized that alignment is the culprit. So I assigned a space of 4 to all the variables I want to write to the Sdram and it works fine
Related
I am using a STM32F415RGT6 embedded in the 1Bitsy Board. I want to set up the I2C Peripheral in order to read some data from a sensor. I am using the stm32f4 standard peripheral library.
My example code:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef gpioInit;
GPIO_StructInit(&gpioInit);
gpioInit.GPIO_Mode = GPIO_Mode_AF;
gpioInit.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
gpioInit.GPIO_PuPd = GPIO_PuPd_UP;
gpioInit.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
GPIO_Init(GPIOB, &gpioInit);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_DeInit(I2C1);
I2C_InitTypeDef I2C_InitStructure;
I2C_StructInit(&I2C_InitStructure);
/* I2C configuration */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x01;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
/* Generate Start, send the address and wait for ACK */
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, 0xE0, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
After that I want to write a 0x00, but the code always hangs in the last line, apparently the Master never reads the acknowledge. The I2C status registers always read:
I2C1 -> SR1 = 1024
I2C1 -> SR2 = 3
which means that the Acknowledge Failure bit is always set. If I analyze it using my Saleae I get the following:
The Slave sends the ACK, but the STM32F415 cannot read it.
The weird thing: If I try the same code on my F407 - Disco (only with clock set to 400khz, but it's the same behaviour on both MCUs regardless of Speed), it works flawlessly:
All other peripherals work fine. I already tried several workarounds, but the AF bit is always set, regardless of method. I hope you can help me.
P.S: I have tried with and without additional pullups and the I2C Slave Address is fine, because it works with STM32F0, STM32F4-DISCO and Atmel Mcus.
Best Regards and Thanks in advance!
As my question says, to access Port by its address, Can we write it as "&PORTA" ??
In my problem, I want to read/write port value from/to HMI, using Modbus Protocol.
I have an array of structure :
typedef struct func_code_reg {
volatile uint16_t addr;
volatile uint16_t *data;
}RW_REG_DATA;
// described as
RW_REG_DATA rwCoilStatusTbl[] = {
// Addr Data_Register
{ 0, &rwCoil_0000 },
{ 1, &rwCoil_0001 },
};
Whenever HMI reads data , it reads the current value of register &rwCoil_000x
Whenever HMI writes data, the register &rwCoil_000x gets updated.
Instead, I would like to use &PORTA to read Port status or to update Port Status.
Is it possible ?? & if possible, is it the correct way to update the Port status ??
Or any better way, please guide me.
(I am using dsPic33E series)
PORTx is already mapped to the contents of the PORTx register, you don't need its address. To read from a port, use the PORTx register. To write, use the LATx register.
So if you want the value rwCoil_000x to be reflected on a port (A), simply write:
LATA = rwCoil_000x;
And if you want to read from the port into the same variable, write:
rwCoil_000x = PORTA;
Of course, this assumes PORTA is set to be a general purpose output.
If you want to generalize over many different ports, you can build an array of volatile references to *PORT.
I did this once for the other way, the outputs, LAT registers, see Using an array of LATs to toggle outputs. type of (byte) pointer to lat
I need to transfer data serially from AT89s52 to Hyperterminal of PC.
For that I made a sample program to print "Hello" on the hyperterminal of my PC by programming the below given code inside 89s52 microcontroller and connecting it to my PC via serial port. Now when I am opening hyperterminal for the respective port, I should be seeing "Hello" printed on the screen multiple times, but what actually I am seeing is some garbage data getting printed.
This is the code I have used.
#include < AT89X52.H>
#include < STDLIB.H>
#include < STDIO.H>
unsigned int i;
void main (void)
{
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
TI = 1;
P1 = 0;
while (1)
{
puts("Hello\r");
P1 ^= 0x01; /* Toggle P1.0 each time we print */
for(i=0;i<25000;i++);
}
}
In the Hyper terminal I am not getting correct output i.e. Hello. Instead I am seeing some Garbage characters..
Can anybody help on this please..?
Can you See P1 is toggling? I would rather send a single character first and observe what is sending by using an oscilloscope. You should see a digital signal corresponding to the ASCII value of the character being split-out from the TX pin of the micro. Also you can check the baud rate (exact value) by using the scope. If you are convinced that the correct value is sent at the right baud rate it is most likely that you got a bad connection or perhaps the baud rate should slightly be changed.
I was trying to pass PORTs address trough a struct by using a function, by i don't know how to correct work with pointers. Here's the code of my struct and function:
typedef struct {
read:1;
last_read:1;
changed:1;
unsigned short *port; //Here the declaration of the pointer that will receive the address
pin:1;
active_state:1;
} Input;
void Setup_input(Input s,char *port, char pin, char active_state){
s.port = &port; //HERE I TRY TO PASS THE ADDRESS OF THE PORT TO THE POINTER OBJECT
s.pin = pin;
s.active_state = active_state;
It turns out that I'm not doing it correctly and I'm not able to read or control correctly the PORT. I'm using Mikroelectronic PRO compilers.
This line of code
s.port = &port;
stores the address of the parameter into the member port. When you dereference the pointer in the structure you will access the stack memory where the parameter port were while calling Setup_input(). This causes undefined behavior.
What you obviously want is to assigne the value of the parameter:
s.port = port;
I have just downloaded the latest Arduino Library code from Github, and it's broken my MQTT client program. I'm using PubSubClient 1.91 on Arduino, and Mosquitto 1.1.2 (Build 2013-03-07) on Mac OSX. (I also tested against Mosquitto on Windows 7, same problem.)
The supplied Mosquitto clients work fine, (Mac over to Windows, Windows over to Mac) so it's some problem with what's coming from the Arduino end. A wireshark trace shows the Arduino client sending the following data packet:
10:15:ff:ff:4d:51:49:73:64:70:03:02:00:0f:00:07:41:72:64:75:69:6e:6f
And the Mosquitto broker shows:
New connection from 10.0.0.115
Socket read error on client (null), disconnecting.
Before I start to crawl through the MQTT spec, can anyone see anything wrong with the data packet being sent? It's got to be something to do with new Arduino library code...
* Update
Upon further investigation, it appears to be a code generation problem with avr-g++, although life experience tells me it will turn out not to be so. Here is a snippet of code from PubSubClient.cpp
boolean PubSubClient::connect(char *id, char *user, char *pass, char* willTopic, uint8_t willQos, uint8_t willRetain, char* willMessage) {
if (!connected()) {
int result = 0;
if (domain != NULL) {
result = _client->connect(this->domain, this->port);
} else {
result = _client->connect(this->ip, this->port);
}
if (result) {
nextMsgId = 1;
uint8_t d[9] = { 0x00, 0x06, 'M','Q','I','s','d','p',MQTTPROTOCOLVERSION};
// d[0] = 0;
// d[1] = 6;
Serial.print("d[0]="); Serial.println(d[0],HEX);
Now, the result of the Serial.print just above turns out to be 0xFF !!! So, the uint8_t array is not being initialised correctly. #knoleary Your pointer to the bad FF bytes lead me to this.
If I now uncomment the two lines above, and manually initialise the first 2 bytes to 0 and 6, all works fine, and my program communicates happily with Mosquitto.
I've looked at the generated code, but I'm not an Atmel expert.
Does anyone have any clue why this might be?
I'm compiling using the AVR-G++ toolset from Arduino 1.05, in Eclipse.
I'm going for a beer!
OK, I found it. It's a relatively subtle bug. Essentially, when the following line of source code is compiled;
uint8_t d[9] = { 0x00, 0x06, 'M','Q','I','s','d','p',MQTTPROTOCOLVERSION};
the 9 bytes get stored as a constant in the data section of the image. At runtime, a small loop copies the 9 bytes into the array (d[]) By looking at a combined Assembler / source listing, I could see where in the data section the 9 bytes were stored, and then print them out at regular intervals, until I found what was over-writing them. (A bit primitive, I know!)
It turns out the there's a bug in WiFi.cpp , the Arduino WiFi code. Here's the code:
uint8_t WiFiClient::connected() {
if (_sock == 255) {
return 0;
} else {
uint8_t s = status();
return !(s == LISTEN || s == CLOSED || s == FIN_WAIT_1 ||
s == FIN_WAIT_2 || s == TIME_WAIT ||
s == SYN_SENT || s== SYN_RCVD ||
(s == CLOSE_WAIT));
}
}
It turns out the the _sock variable is actually initialised like this:
WiFiClient::WiFiClient() : _sock(MAX_SOCK_NUM) {
}
and MAX_SOCK_NUM is 4, not 255. So, WiFiClient::status returned true, instead of false for an unused Socket.
This method was called by the MQTT Client like this:
boolean PubSubClient::connected() {
boolean rc;
if (_client == NULL ) {
rc = false;
} else {
rc = (int)_client->connected();
if (!rc) _client->stop();
}
return rc;
}
And, since the _client->connected() method erroneously returned true, the _client_stop() method was called. This resulted in a write to a non-existent socket array element, and so overwrote my string data.
#knolleary, I was wondering, is there any specific reason that your PubSubClient::connected() method does a disconnect? I use the ::connected method in a loop, to check that I'm still connected, and, of course it results in my getting a disconnect / reconnect each time round the loop. Any chance we could just make connected return true / false , and handle the disconnect in PuBSubClient::connect?
Nearly one and a half year later I ran into the same problem. Removing the
boolean PubSubClient::connected() {
int rc = (int)_client->connected();
if (!rc) _client->stop();
return rc;
}
the _client->stop() from the connected method of PubSubClient forehand fixed this problem for me. However, I'm not sure whether this is actually a solution or just a very dirty quick hack to localize the problem.
What have you done to fix this problem - your explanation of the problem above is fine however, I was not able to extract the solution easily ;-)