Help to port a library from AVR to stm32! - Page 1
Forum section: electronics / general

author: kgavionics
author_rank: Regular Contributor
timestamp: May 28, 2023, 11:57:47 pm
content: Hello guysI'm trying to port a Nokia5110 display from AVR to Stm32, but I have a problem with printing characters stored on the flash, the rest is working fine!The original library is using program space to read from the flash memory :Code:void N5110_PrintStr(uint8_t x, uint8_t y, char *str, bool set){uint8_t f_width = pgm_read_byte(&CurrentFont);uint8_t length = strlen(str);for(int i = 0; i < length; i++){N5110_PrintChar(x + (i * f_width), y, *str++, set);}}for the stm32, I just removed pgm_read_byte:Code:void N5110_PrintStr(uint8_t x, uint8_t y, char *str, bool set){uint8_t f_width = (&CurrentFont);uint8_t length = strlen(str);for(int i = 0; i < length; i++){N5110_PrintChar(x + (i * f_width), y, *str++, set);}}the fonts are stored like this:Code:const uint8_t SmallFont[] ={/* Width, Height, Offset, Number */0x06, 0x08, 0x20, 0x5f,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // "0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $0x00, 0x23, 0x13, 0x08, 0x64, 0x62, // %0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 00x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 10x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 20x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 30x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 40x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 50x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 60x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 70x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 80x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 90x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, // Backslash (Checker pattern)0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _0x00, 0x00, 0x03, 0x05, 0x00, 0x00, // `0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, // z0x00, 0x00, 0x10, 0x7C, 0x82, 0x00, // {0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, // |0x00, 0x00, 0x82, 0x7C, 0x10, 0x00, // }0x00, 0x00, 0x06, 0x09, 0x09, 0x06 // ~ (Degrees)};Can someone tell me what I'm doing wrong! TIA

author: brucehoult
author_rank: Super Contributor
timestamp: May 29, 2023, 12:15:22 am
content: Code:pgm_read_byte(&CurrentFont);You should consider how you would actually implement pgm_read_byte for the ARM...Code:char pgm_read_byte(char *p){return *p;}... and then do the same actions instead of the call.(and then simplify the resulting code, though it's not necessary as the compiler will do that for you)

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 29, 2023, 12:27:25 am
content: Quote from: kgavionics on May 28, 2023, 11:57:47 pmYou're assigning the address of the item instead of its value.

author: hans
author_rank: Super Contributor
timestamp: May 29, 2023, 09:04:05 am
content: Since the font is marked 'const', it is stored in FLASH. AVR and some other 8-bit MCUs uses a Harvard architecture. This means the FLASH memory has its own address space. You can get pointers to things that are stored in FLASH, but dereferencing it with '*pointer' would read it from the data memory instead. So that's why AVRs use pgm_read_byte, which internally use a special instruction of the CPU to read FLASH data.On ARM and many other architectures that can support a wider address bus, they have chosen for a Von Neumann architecture. Here instruction and data are within the same address space, and so you don't need special instructions anymore. You can just replace pgm_read_byte by the a placeholder as bruce shows. If you turn on the compiler optimizer (if you need the speed), that function will disappear in its enterity.

author: kgavionics
author_rank: Regular Contributor
timestamp: May 29, 2023, 12:18:09 pm
content: Quote from: brucehoult on May 29, 2023, 12:15:22 amThank you, brucehoult, your solution worked like a charm!

author: kgavionics
author_rank: Regular Contributor
timestamp: May 29, 2023, 03:23:59 pm
content: Quote from: hans on May 29, 2023, 09:04:05 amNo man, the Stm32F4 I'm using is based on Harvard architecture!

author: Siwastaja
author_rank: Super Contributor
timestamp: May 29, 2023, 04:06:13 pm
content: Quote from: SiliconWizard on May 29, 2023, 12:27:25 amThe best answer because it shows the mistake instead of just suggesting something that works.Original access function wantedan addressto return the value. When you don't need such a function in a sane unified address space MCU, you want to just... use the value, not the address anymore. array operator gets a value from an array. &array would get the address of that value, which is not what you need here anymore.

author: HwAoRrDk
author_rank: Super Contributor
timestamp: May 29, 2023, 04:30:18 pm
content: Quote from: kgavionics on May 29, 2023, 03:23:59 pmWhile that is technically correct, in that the F4 has multiple buses internally, it essentially acts like a von Neumann architecture as far as the programmer is concerned.See this Stack Exchange question for more information:https://electronics.stackexchange.com/questions/616764/why-do-we-see-one-unified-memory-address-space-in-arm-cortex-m-core-based-mcus

author: kgavionics
author_rank: Regular Contributor
timestamp: May 29, 2023, 08:08:17 pm
content: Quote from: SiliconWizard on May 29, 2023, 12:27:25 amYou're absolutely right! After assigning the value instead of the address, it did work! Thanks!

author: brucehoult
author_rank: Super Contributor
timestamp: May 30, 2023, 12:55:12 am
content: Quote from: Siwastaja on May 29, 2023, 04:06:13 pmHow is that?I showed that the pgm_read_byte function took the address of a character, dereferenced it, and returned the character.Code:pgm_read_byte(&CurrentFont)char pgm_read_byte(char *p){return *p;}... and suggested that you should inline this function rather than simply deleting the name ...Code:*&CurrentFont... and that you could then simplify the expression ...Code:CurrentFontHow is this not a good answer?(I described the steps to be mentally taken, but didn't spell them out in detailed code, as above, because I think it is a good idea if the OP does a little thinking for themselves, not simply being handed the finished result)

author: Siwastaja
author_rank: Super Contributor
timestamp: May 30, 2023, 08:27:51 am
content: Quote from: brucehoult on May 30, 2023, 12:55:12 amThe problem SiliconWizard saw is that OP clearly did not understand the C language enough to know what operator & means. Therefore, the OP likely does not understand why your code example works, because they likely do not understand what * operator in the function body is doing, either. You just posted code which is equivalent level of complexity for a beginner than the original code, without explaining any of the operators used andwhyit works (which is all obvious for someone who understands C better, but they would not be posting the question). This is why I consider SiliconWizard's reply the best.

author: brucehoult
author_rank: Super Contributor
timestamp: May 30, 2023, 11:48:53 am
content: I certainly hope OP is not so bad at C while doing such work, and I would never assume someone with "avionics" in their name could be! I hope and assume the problem is merely grabbing an AVR library and not understanding accessing of data in flash on them, as they don't normally use them.

author: DavidAlfa
author_rank: Super Contributor
timestamp: May 30, 2023, 02:23:26 pm
content: Definitely this is a nope:Code:void N5110_PrintStr(uint8_t x, uint8_t y, char *str, bool set){uint8_t f_width = (&CurrentFont);Possible fixes(Both do the same thing):Code:uint8_t f_width = CurrentFont;uint8_t f_width = *CurrentFont;You better post N5110_PrintCharfunction too...

author: kgavionics
author_rank: Regular Contributor
timestamp: May 30, 2023, 02:52:19 pm
content: Quote from: DavidAlfa on May 30, 2023, 02:23:26 pmAs I mentioned before, I removed the address symbol(&) and everything is working fine!

author: kgavionics
author_rank: Regular Contributor
timestamp: May 30, 2023, 02:56:11 pm
content: I never pretended that I'm a professional in C language, I'm a hobbyist, My job is an Avionics Technician and I never code in my trade, but I can assure you I code better than some useless people here. Furthermore, I did not post this question in a professional C programming forum, so for whom they pretend to be knowledgeable in coding stop making fun of people! So that would be my last coding question that I'll ever post in this forum!

author: Siwastaja
author_rank: Super Contributor
timestamp: May 30, 2023, 03:28:54 pm
content: Yes. It's worth remembering many hobbyists and even total beginners post on these forums and it's completely OK.

author: DavidAlfa
author_rank: Super Contributor
timestamp: May 30, 2023, 05:32:42 pm
content: Quote from: kgavionics on May 30, 2023, 02:52:19 pmNice then! Sorry, opened the post, SAW THAT, then I HAD to write the message no matter what!Yeah pointers are a bit messy at first! I still remember some years ago I mentally called->"That weird arrow thing of C"

author: Siwastaja
author_rank: Super Contributor
timestamp: May 30, 2023, 05:42:44 pm
content: Every single of us have been at a stage where we don't understand pointers. I still remember the time when I just randomly tried different combinations of *, & etc. until it (1) compiled without warnings, (2) worked. Only years later I got this greatest idea ever that life would be easier if I always tried to understand what I'm doing. But at first everything is overwhelming so you just try random things.C++ adding a separate concept of references which is the same thing but with partially implicit, partially explicit syntax and reuse of the same & operator made everything much worse.

author: kgavionics
author_rank: Regular Contributor
timestamp: May 30, 2023, 07:59:12 pm
content: As some of you guys said I'm bad in C, I ported this library (see link below) to stm32f4 by myself and I only got stuck in the pointer thing. And by the way I know that the operator means the adress, but I wasn't paying attention enough which can happens to even veteran coders, but it's not a big deal, because I learned from my mistakes, but I didn't like the way that some posters were bragging about their proficiency in coding and try to make me look stupid, which I'm not!https://github.com/eziya/AVR_NOKIA5110

author: elecdonia
author_rank: Frequent Contributor
timestamp: May 31, 2023, 07:07:28 pm
content: Quote from: Siwastaja on May 30, 2023, 05:42:44 pmBeen there, done that.I’m usually eager to learn how & why things work in certain ways (but fail in other ways). But sometimes I just want my code to compile, run, and do what I want it to do. And I also wish to get to this point as quickly as possible. For this my fall-back method is to study working source code written by others to glean the “secrets” which allow that code to work. I’ve collected vast amounts of C and C++ source code to search through. Most of my reference material is in the form of Arduino libraries and related projects posted at GitHub.

author: brucehoult
author_rank: Super Contributor
timestamp: June 01, 2023, 01:17:54 am
content: Quote from: kgavionics on May 30, 2023, 07:59:12 pmYou've said this a few times now, and I'm scratching my head who you are talking about.For example, my assumption was that you know what "&" and "*" do, but perhaps were using an AVR library without being familiar with AVR, and had simply missed the extra "&" (we all make mistakes) and were smart enough to figure it out with a bit of a hint.

author: peter-h
author_rank: Super Contributor
timestamp: June 01, 2023, 08:29:22 am
content: kgavionicsThis is from another "avionics player" (spent much time on arinc429)and from a different angle.I've wasted a lot of my time with code which was ex github or whatever and which worked only with no compiler optimisation. The problem is that a lot of code was written for some 16MHz CPU and when you run it at 168MHz or whatever, the timing of the device being driven is no longer met. So check it with a scope.Also remember that much code online doesn't work anyway. A lot of people get a kick out of publishing their hobby code online and when they get bored, or just can't get it to work and move on, they leave it online. Then 100 people separately download it, 100 of them separately work out why it doesn't work, 100 of them waste a lot of time...FWIW I avoid pointers. I go as far as passing variables by address (unavoidable in C if you want to return more than one thing from a function) but don't use the * pointer notation for fun, as "real coders" doI use arrays and an explicit index. The resulting compiled code is probably the same.

author: kgavionics
author_rank: Regular Contributor
timestamp: June 01, 2023, 02:15:11 pm
content: Quote from: peter-h on June 01, 2023, 08:29:22 amThank you peter for your advice, it's very much appreciated !

author: elecdonia
author_rank: Frequent Contributor
timestamp: June 01, 2023, 02:22:00 pm
content: Quote from: elecdonia on May 31, 2023, 07:07:28 pmOne of my favorite places for finding code to study is the Teensy project (PJRC and Paul Stoffregen) which contains its own Teensy-focused forum:https://forum.pjrc.com/When I search for examples of well-written code at GitHub I frequently sort the search results by “most stars.” Projects which earned hundred or thousands of stars are generally well-written. Here are some that I like:https://github.com/arendst/TasmotaESP8266 & ESP32 firmware19k starshttps://github.com/micropython/micropythonMicropython16khttps://github.com/RT-Thread/rt-threadStandard & Nano versions8.5khttps://github.com/FastLED/FastLEDFastLED5.8khttps://github.com/olikraus/u8g2monochrome displays4khttps://github.com/blynkkk/blynk-libraryBlynk project3.6k