Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


holdmybeer last won the day on September 4

holdmybeer had the most liked content!

Community Reputation

8 Neutral

About holdmybeer

  • Rank

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Welcome to our forum, ingbaker. Can you elaborate your question a bit more, please?
  2. I've got a tip from a colleague: Doxygen also generates dependency and call graphs for a project. So I ran it and after an hour of tweaking and installing things that Doxygen also requires to run I ended up with a nice graph: It doesn't say if the header is actually used by a module, but it certainly is something to get a quick overview of what I'm about to integrate into my project. I always thought of Doxygen being a documentation tool, never thought about the possibility to explore an unknown project with that. Very nice!
  3. I completely agree with you! I try to avoid comments, because they tend to de-synchronize with the actual code very easily. #pragma config PWRTE = ON // Power-up Timer Enable bit->Power up timer disabled What does that mean? Is it a bugfix? Is it a bug? I find this so often in mature projects. Someone edited bit masks for a register, but forgot to update the comments. Even the Hungarian notation as an extended version of commenting de-synchronizes eventually, because you tend to ignore the prefixes after a while. uint32_t u16counter; So my personal approach is to find identifiers and names to formulate a readable code, which says everything what is actually happening on that specific line of code. There is no need to write functions with many lines of code to make the compiling more efficient or save stack space, modern compilers will optimize that out again. Encapsulating a partial solution not only brings structure to your code, it makes the function actually readable. And with readable I mean to read it out loud in front of an audience (e.g. for a code review). Comments should give the reader a general overview of the problem and an abstract strategy what has to be done in a function. If the purpose is obvious and easily derivable from the identifiers, why create a second meta layer which needs extra maintenance and creates a dependency? This in turn often means that an over-commented code doesn't have a good structure or the author doesn't understand the problem well enough to abstract it. Although sometimes the project dictates code metrics, like a code to comment ratio that has to be satisfied. I see a lot of projects with Doxygen comments in it, but the actual content of that documentation is rather unhelpful.
  4. I struggle to import a certain feature into my microcontroller project. One of my "init" projects needs an eeprom emulation feature and I found a fitting solution. However, the project comes with a dozen ASF files which might be needed, maybe not. To further complicate things, I don't need their hardware initialization. So I could strip their system init function, which leads to more potentially dead files in the project. Is there a more convenient way to get an overview of all the dependencies than clicking through all the includes and declarations manually? I have the feeling I don't need most of the files, but the project is a bit too large to rewrite everything. If I would be very lazy, I'd just throw the whole directory in my project. But I guess this won't end well... So what is your opinion?
  5. I was able reproduce that, XC16 and XC32 seem to strip the quotes from your string literal definition, no matter what you do 😞
  6. For me, the trick to strictly read it from right to left helped a lot. volatile List_t * ListHead; A variable ListHead which is a pointer to the type List_t which is volatile. List_t * volatile ListHead; A variable ListHead which is a volatile pointer to a type List_t volatile List_t * volatile ListHead; A variable ListHead which is a volatile pointer to a type List_t which is volatile const int *ptr_to_constant; A variable ptr_to_constant which is a pointer to a type int which is a constant int *const constant_ptr; A variable constant_prt which is a constant pointer to a type int
  7. Not every pin is capable of driving such high frequencies. I strongly suggest to have a look at the output signal with a scope. Are the edges of the signal okay or do they get rounder and rounder with increasing baud rate? Is the frequency correct? A few pins may have special hardware (such as SPI) to have more drive strength, have a Schmitt trigger behavior for inputs etc.
  8. My SAME54 project is growing every day, and I have to make a decision how to manage my code. Maybe someone has an advise for me? The situation is this, I started to develop the project in Studio. Later, some people persuaded my to rebuild my project to work with XC32 along with the headers from XC. So I made a branch "MPLABX_Branch" to put the modified project there. Now I have a complete parallel branch with different register names and it's quite a pain to maintain them both if I want to add something new. Should I put the branch into a new repository? Or should clutter up the code with a lot of #ifdefs for XC and GCC? What would be the best approach?
  9. According to your zip package, PBCLK is set to 48 MHz, not 96MHz? And it's a PIC32MX470F512L, just for clarity 🙂 It would be a good idea to debug your project and have a look at the actual register settings, to see if Harmony did everything right. I would also suggest to check the analog output signal with a scope to check the frequency and the signal quality. Is there a signal at higher baud rates and how does it look like?
  10. And now it works with 2.15. Try to add "extern" to your inline function, this worked for me:
  11. Oh, I see now. You have to include the body, otherwise the compiler complains (if -Winline is used): my_inline_func.h:4:17: warning: inlining failed in call to 'inl_func': function body not available [-Winline] And it works fine with 2.10, I see nice inlined functions in the disassembly:
  12. I just had a look at your test project and really wonder why you put the definition of a function in a header file. Since you include that header file with the definition in two C files, you end up with two conflicting definitions, don't you?
  13. No you haven't, right. This only was my conclusion for my original idea 🙂 The key for filtering the output string was activating line buffering, then the _write function will be called with a larger string which can be filtered well. If buffering is set to off or if filtering is implemented in putchar, you would have to set up a little state machine to keep track of the characters already written.
  14. error: 'cmse_nonsecure_entry' attribute not available to functions with variable number of arguments This is what I saw today on my screen 😂 So I had no other choice than exposing _read and _write as a non-secure entry. The write function filters out all non-printable chars and adds the prefix before the string. Another challenge was to bring printf to not print char by char, I had to turn on line buffering: setvbuf(stdout, NULL, _IOLBF, 80); I still have trouble understanding how a function call from non secure to secure and back looks like from the perspective of the stacks (it has two stack pointers). Have a look at my Github if you like, I'm open for critical reviews. Anyway, filtering printf format strings would work, but gets complicated very quickly with all these possible combinations of parameters, flags, etc. It would quickly end up in building a parser for the format string. I didn't foresee how deep the problem actually is when I started this thread 🙂 Thanks for your input!
  • Create New...