tag 标签: coding

相关博文
  • 热度 22
    2016-2-5 19:08
    1205 次阅读|
    0 个评论
    It's not that I can’t write C per se -- it's just that I don’t write very good C (LOL). Thus, I'm currently on a quest to learn C/C++.   The problem is that I'm a hardware design engineer by trade. I dabble at programming -- now mostly as part of my hobby projects -- and I largely make things up as I go along. The end result is that I tend to spend an inordinate amount of time debugging my code. Sometimes the simplest thing can trip me up for ages. For example, I recently took a global int declaration that looked something like the following...   int pinTiming = 7; ...and I converted it into a #define directive that looked something like the following... #define pinTiming 7; This isn't the exact example, but it's close enough for you to get the idea. As you can see, I remembered to remove the equal symbol, but I forgot to strip out the semicolon at the end. I also made a few other tweaks throughout the body of the program. "This is wasy-peasy," I thought to myself... until I tried to compile the little scamp and the compiler hung up. Initially, I focused on the changes I’d made to the body of the program, so it took me ages to track this little rapscallion down.   One problem I have is that I've fallen into the trap of wanting my programs to look like "big boy code." In the past, I've seen code written by professional programmers that has been concise and sparing in its use of white space characters, and that has given the impression that its creator knew "what was what." On the other hand, this code has also often been cryptic and hard to read.   If you work for a large company, they will probably dictate the coding style you use. If you work for a smaller company, it may be more of a "free for all." And if you are an individual, you're pretty much on your own.   There are a lot of books on programming, but they typically focus on teaching the use of the various language operators and constructs. When it comes to coding "style," different books tend to reflect the personal preferences of the author. Take the following two versions of the same snippet of code, for example:   // Version A for(i=1;i10;i++){ // Statements go here } // Version B for (i = 1; i 10; i++) { // Statements go here } Should there be a space after the for (Version B) or no space (Version A)? Should we use white space to separate things out between the standard parentheses (Version B) or no white space (Version A)? Should the opening squiggly bracket appear on a new line (Version B) or on the same line as the for (Version A)? Should we indent the statements forming the body code using four spaces (Version B), two spaces (Version A), or some other number of spaces?   Where do you go to learn this sort of thing? Well, I know where I go, because I just read the Embedded C Coding Standard by Michael Barr of the Barr Group . At only 88 pages, this isn’t a large tome, but as far as I'm concerned it's worth its weight in gold. The really good news is that it's only $9 for a PDF download and the same for a hard copy (print version) shipped by standard mail in the USA (it's $19 for a hard copy shipped anywhere else in the world).   (Source: BarrGroup.com)   The overriding reason Mike and his colleagues created this standard is to reduce the number of bugs in embedded software (a.k.a. firmware), including code added or modified later by maintainers.   I was chatting with Mike on the phone just a few minutes ago as I pen these words. He acknowledged that a lot of code writing comes down to personal preference, so -- when it came to creating this standard -- he and his co-contributors sat around the table arguing each point. The only criterion for selecting one style rule over another was that rule's ability to minimize potential bugs.   The book is divided into major sections, like Comments, White Space, Data Types, Variables, and so forth. Each of these sections is then sub-divided into a number of topics. In the case of White Space, for example, we have sub-topics of Spaces, Alignment, Blank Lines, Indentation, Tabs, and Linefeeds.   As an aside, the term Whitespace (paradoxically containing no spaces) is an esoteric programming language developed by Edwin Brady and Chris Morris at the University of Durham Its name is a reference to white space characters. As it says on the Whitespace page on Wikipedia: Unlike most programming languages, which ignore or assign little meaning to most white space characters, the Whitespace interpreter ignores any non-whitespace characters. Only spaces, tabs and linefeeds have meaning. An interesting consequence of this property is that a Whitespace program can easily be contained within the whitespace characters of a program written in another language...   But we digress... each of the sub-sections starts off with its associated rules. These rules are followed by the reasoning behind them, any permissible exceptions, and the ways in which the rules are to be enforced.   Let's take the use of braces (squiggly brackets), for example. Over the years, I've bounced back and forth between having the left brace ('{') appear on the same line as its if , else , for etc. statement, or having it appear by itself on the line below the start of the block it opens. Here's what the Embedded C Coding Standard has to say: Braces: Rules: Braces shall always surround the blocks of code (a.k.a. compound statements) following if, else, switch, while, do, and for statements; single statements and empty statements following these keywords shall also always be surrounded by braces. Each left brace ('{') shall appear by itself on the line below the start of the block it opens, The corresponding right brace ('}') shall appear by itself in the same position the appropriate number of lines later in the file. Reasoning: There is considerable risk associated with the presence of empty statements and single statements that are not surrounded by braces. Code constructs like this are often associated with bugs when nearby code is changed or commented out. This risk is entirely eliminated by the consistent use of braces. The placement of the left brace on the following line allows for easy visual checking for the corresponding right brace. What can I say, except that I totally agree with all of these points? I've tried having the left brace on the same line as my if and for statements because I thought it made my code look "professional." As a result, I've spent an inordinate amount of time trying to determine which left brace was associated with which right brace.   I've also tried omitting braces when I had only a single statement. Once again, I did this because I thought using these braces would make professional programmers think I was a weed and a wet who didn’t have a clue. This is all the more pathetic when we come to realize that no one but myself ever looks at my code anyway. But having read this standard, I feel empowered to use braces for everything: multiple statements, single statements, and even empty statements.   In the case of indentation, the first rule says "Each indentation Level within a module should consist of 4 spaces" (there are additional rules that modify this first rule as necessary). The reasoning behind this reads as follows: "Fewer indentation spaces increase the risk of visual confusion, while more spaces increases the likelihood of line wraps."   Once again, I'm forced to agree with this. I've been using two spaces for indentation because this is what I've seen others use, but I just tried using four spaces on a block of my existing code and the result is much more readable. One rule that almost made me squeal with delight was in regard to equivalence tests. This rule reads as follows: "When evaluating the equality or inequality of a variable with a constant value, always place the constant value on the left side of the comparison operator." What they are saying here is to use if (MAX_LOOP == loop_count) instead of using if (loop_count == MAX_LOOP) . The reason for doing this is that, in the case of the former, the compiler will flag an error if we mistakenly use a single assignment "=" instead of a dual equivalency "==". I cannot tell you how many hours my implementing this rule would have saved me in the past.   I tell you -- I read the Embedded C Coding Standard in only one evening, but it's going to dramatically change the way I write my programs in the future. So, now all I need to do is to learn C itself (LOL). Watch this space for future developments...
  • 热度 16
    2015-11-3 17:57
    1798 次阅读|
    0 个评论
    Before we begin, I should remind you that I am a hardware design engineer by trade -- I am in no way a paid-up member of the software cognoscenti -- so when it comes to creating code, I'm largely reduced to making things up as I go along.   Of course, this sometimes ends up with my feeling as though I'm on the losing end of a birling competition, but I love the adrenalin rush of excitement and anticipation when I finally track a recalcitrant bug -- typically in the form of a stupid mistake on my part -- down to its lair.   The point is that, even though I do walk the path of hardware righteousness, I have picked up a few tricks from the software dark-side along the way, and I'm quite proud of some of these little rascals, so I thought I'd dare to share them here.   Now, if you are one who strides the corridors of power in the software domain, you'll probably see this article as an amphigory describing paltry parlor tricks of no account, in which case may I bid you good day (don’t let the door bang into you on the way out). We hardware guys and gals have enough on our plates wrestling the underlying systems into submission, so when it comes to subduing scoundrelly software, all we can do is do the best we can with what we've got.   The topic of this article is implementing interesting effects on LED rings -- in particular, the NeoPixel-based rascals from Adafruit that I've been using in my Vetinari Clock and Cunning Chronograph projects.   In the case of the Vetinari Clock, we're working with a 16-element NeoPixel ring. For the purposes of simplicity, however, let's pretend it's an 8-element ring, and that these elements are numbered as follows (I've shown element 0 as being a darker color for future reference):   Let's assume that we've declared our ring and -- because we don’t have much imagination -- we've called it myRing . Let's also assume that we've already defined our 8-bit RGB values, which we will refer to as R , G , and B in the code (I hope this naming convention won't prove to be too confusing :-)   Now, let's suppose that we wish to light up the elements forming our ring one after the other, starting with element 0 and working out way up to element 7, with a 100 ms delay between each of the elements turning on. After this, we wish to turn them off again in the same order. The code we use to do this could be as follows: for (i = 0; i 8; i++) { myRing.setPixelColor(i,R,G,B); myRing.show(); delay(100); } for (i = 0; i 8; i++) { myRing.setPixelColor(i,0,0,0); myRing.show(); delay(100); } The way Adafruit's NeoPixel library works is that the setPixelColor() function stores the RGB data in an array in memory (we might visualize this as a two-dimensional array of bytes called myRing , where the first dimension reflects the number of elements forming the ring and the second dimension refers to the three RGB values associated with each element). Later, we use the show() function to stream this data out of memory and into the ring. (Note that the 8 and 3 values in the array declaration result in elements numbered 0-to-7 and 0-to-2, respectively.) OK so far, but now let's suppose that every time we light up a new element ( i ), we also wish to turn off the previous element ( i - 1 ), perhaps using something like the following: for (i = 0; i 8; i++) { myRing.setPixelColor(i,R,G,B); myRing.setPixelColor(i-1,0,0,0); myRing.show(); delay(100); } The idea is that if we were to call this snippet of code over and over again, we would hope to see a single element racing round and round the ring. The problem is that the code shown above won’t work (cue "sad sound" effect). The underlying theory is reasonable enough, but it's always the "end conditions" that bite you in the nether regions when you're least expecting it. In order to see what the issue is, consider the following table:   As we see, the problem occurs right at the beginning when we illuminate element 0 and attempt to turn off the previous element. We actually wish to turn off element 7 (00000111 in binary). The problem is that when i = 0 , our i - 1 operation will result in -1 (11111111 in binary). If you aren’t sure where this 11111111 value came from, but you really wish to know, then you need to perform a Google search on "Two's Complement." For the purposes of this column, however, let's simply assume that -1 in our computer is represented using an all 1s value. Now, we could perform a test to see if we are working with bit 0, and address the situation accordingly. Consider the following snippet of code, for example: for (i = 0; i 8; i++) { myRing.setPixelColor(i,R,G,B); if (i == 0) myRing.setPixelColor(7,0,0,0); else myRing.setPixelColor(i-1,0,0,0); myRing.show(); delay(100); } This is certainly a serviceable solution, but I regard it as being messy and aesthetically unpleasing. Fortunately, there's a cunning trick we can employ as follows: for (i = 0; i 8; i++) { myRing.setPixelColor(i,R,G,B); myRing.setPixelColor((i-1) 0x7,0,0,0); myRing.show(); delay(100); } The is known as the bitwise AND operator. This operator performs a logical AND operation on each pair of corresponding bits in the values on either side of the operator. If either of the bits is 0, the associated output bit is 0; it's only when both bits are 1 that the output is 1. Consider what would happen if we were to perform the bitwise AND on two 8-bit variables called a and b containing binary values of 00001111 and 01010101, respectively: (Source: Max Maxfield/Embedded.com) If we look at the two digits in the bit 7 positions, we have 0 0 = 0. The two digits in bit 6 give us 0 1 = 0; the two digits in bit 3 give us 1 0 = 0; and the two digits in bit 2 give us 1 1 = 1. Returning to our code snippet above, we're using the 0x7 as a "mask" to clear the most-significant (MS) bits to 0 and to only return the values in the three LS bits (where 0x7 in hexadecimal represents 00000111 in binary). What this means in practice is that when i = 1 through 7 (00000001 through 00000111 in binary), and i - 1 = 0 through 6 (00000000 through 00000110 in binary), then the 0x7 has no effect whatsoever. However, when i = 0 (00000000 in binary), and i - 1 = -1 (11111111 in binary), then using the bitwise AND ( 0x7 , or 00000111 in binary) results in 00000111, which equates to element 7, which is what we wanted in the first place (cue "happy music"). Our new solution also works "the other way round," as it were. In the examples above, our illuminated element has been racing round in a clockwise direction, but suppose we wished to make it rotate the other way round. Once again, we might start with the following code: for (i = 7; i = 0; i--) { myRing.setPixelColor(i,R,G,B); myRing.setPixelColor(i+1,0,0,0); myRing.show(); delay(100); } And, once again, this won’t work due to a problem with the end condition as illustrated below:   Happily, the same solution we came up with to address the clockwise end condition problem also works for its anticlockwise counterpart: for (i = 7; i = 0; i--) { myRing.setPixelColor(i,R,G,B); myRing.setPixelColor((i+1) 0x7,0,0,0); myRing.show(); delay(100); } In this case, when i = 6 through 0 (00000110 through 00000000 in binary), and i + 1 = 7 through 1 (00000111 through 00000001 in binary), then the 0x7 has no effect. However, when i = 7 (00000111 in binary), and i + 1 = 8 (00001000 in binary), then using the bitwise AND ( 0x7 , or 00000111 in binary) results in 00000000, which equates to element 0, which -- once again -- is what we wanted in the first place. This is the point when I feel like enthusiastically exclaiming "Tra-la" in strident tones; but wait, because there's more (Oh, so much more)... Using cross-reference tables Let’s assume that we are still playing with an 8-element ring and that we've spent countless yonks developing copious amounts of capriciously cunning code. Unfortunately, something dire happens to our ring and we have to replace it. Even worse, when we come to "light up" our new ring, we discover that we've inserted it incorrectly such that it's rotated clockwise by 90° as illustrated below.   In this case, the red numbers outside the ring are the actual indices to the physical pixels, while the green numbers inside the ring reflect the indices our code is expecting to use. It probably goes without saying that this is the time when one is prone to murmur something like "Oh dear, I wish I'd listened to my dear old mother and refrained from supergluing this little scamp into the system" (or words to that effect). Of course, this won't really matter if all we want to do is have one element chasing itself around and around the ring ad infinitum , but it's going to be a real pain if we wish to control specific elements and showcase sophisticated sequences (I tell you, the words are just tripping and trilling off my tongue today). One solution is to create a cross-reference table (array) as illustrated below: int xref = {6,7,0,1,2,3,4,5}; Now, let's take our original "single element chasing itself clockwise around the ring" code snippet as an example: for (i = 0; i 8; i++) { myRing.setPixelColor(i,R,G,B); myRing.setPixelColor((i-1) 0x7,0,0,0); myRing.show(); delay(100); } All we have to do is to modify any references to i in our setPixelColor() function call such that they are redirected by our cross-reference array as illustrated below: for (i = 0; i 8; i++) { myRing.setPixelColor( xref ,R,G,B); myRing.setPixelColor(( xref ) 0x7,0,0,0); myRing.show(); delay(100); } Well, I don’t know about you, but I think this is pretty nifty! Handling rings that don’t have 2^n elements The reason the 0x7 solution worked in our previous examples is that our rings had eight elements, and eight is a power of two (2^3 = 8). Similar solutions can be employed for any other power of two; for example, 2^4 = 16, so 0xF (00001111 in binary) would work with a 16-element ring. Unfortunately, our solution will not work with rings that don’t have 2^n elements. Consider a ring with only six elements, as shown below, for example:   In this case, the only legal values we have to address our elements are 0 through 5 (00000000 through 00000101 in binary). In the case of a clockwise rotation, when we are lighting element i = 0 , our 0x7 solution to extinguish element i -1 would return 7 (00000111), not the 5 (00000101) we desire. Once again, our cross-reference table (array) comes to the rescue. In this case, we could use the following array to support clockwise rotations: int xref = { 5, 0,1,2,3,4,5}; Observe that we've created a 7-element array, even though our ring boasts only 6 elements. This is because we've added an extra entry at the beginning of the array to handle the i - 1 case for when we are illuminating element 0 and extinguishing element 5. In this case, our code snippet would look like the following: for (i = 1; i 7; i++) { myRing.setPixelColor(xref ,R,G,B); myRing.setPixelColor(xref ,0,0,0); myRing.show(); delay(100); } Note especially that we now use i = 1; i 7; in our for loop, as opposed to the i = 0; i 6; we might have used if we hadn’t added the extra element into the beginning of the array. Similarly, if we wish to rotate the illuminated element in an anticlockwise fashion, we would add one more element onto the end of our cross reference array as follows: int xref = {5,0,1,2,3,4,5 ,0 }; Well, things are looking pretty sweet so far, but I'm about to drop a wrench into the works. The above solutions are great if all we wish to do is light up one pixel and extinguish its adjacent companion, but what happens if we wish to do more? Let's suppose, for example, that we are performing a clockwise rotation on a ring containing eight elements. Furthermore, let's suppose that, when we light up element i with RGB values of 255, we also wish to assign element i - 1 RGB values of 127, element i - 2 RGB values of 63, element i - 3 RGB values of 31, and that we wish to extinguish element i - 4 by assigning it RGB values of 0. The overall effect we're trying to achieve is something like a vapor trail fading away. We could, of course, extend our cross-reference array to look like the following: int xref = { 4,5,6,7, 0,1,2,3,4,5,6,7}; And then we could change our corresponding code snippet to look like the following: for (i = 4; i 12; i++) { myRing.setPixelColor(xref , 255,255,255); myRing.setPixelColor(xref ,127,127,127); myRing.setPixelColor(xref , 63, 63, 63); myRing.setPixelColor(xref , 31, 31, 31); myRing.setPixelColor(xref , 0, 0, 0); myRing.show(); delay(100); } I think you'll agree, however, that things are starting to get a little frayed around the edges. Can you think of a solution to this conundrum? What we're looking for is an approach that will let us work with arbitrary numbers of arbitrarily-sized rings (i.e., varying number of elements), and that will facilitate our implementing effects such as having arbitrarily-long "vapor trails," for example. By some strange quirk of fate, I happen to have just such a solution. Let's take a look, shall we...   A plan so cunning... What we are talking about here is a cunning plan. Indeed, "A plan so cunning we could pin a tail on it and call it a weasel," as Black Adder might say. Now, a real programmer would probably have come up with something like this solution right from the get-go, and a real programmer would probably have decided to use pointers. Let's start by assuming we are working with a single ring and that this ring has six elements numbered 0 through 5. Based on this, our hypothetical programmer might have defined a structure containing "previous" and "next" pointers, along with any other desired data fields. Our software guru might subsequently have instantiated a bunch of these structures and connected them together as illustrated below:   Using this construct, it would be possible to implement all sorts of engaging effects relatively easily. Sad to relate, however, there are several problems with this approach, not the least being the fact that I no longer remember how to use pointers. (I used to be a diva with these little rascals 30+ years ago, but a lot of Pooh Sticks have flowed down the river of time since those halcyon days.) Another issue is memory utilization. I'm not sure how big a pointer is in an Arduino Uno -- these things are system dependent -- but it's got to be at least two bytes. This isn’t really an issue if you are playing with a single ring containing only six elements, but things start to mount up when you are working with something like my Cunning Chronograph. For all these reasons, my solution is to implement something like the structure shown above, but using arrays of bytes instead of pointers. (The reason for using 8-bit bytes as opposed to the Arduino Uno's 16-bit integers is that it saves memory. Each byte can happily represent values from 0 to 255, and I have only 96 elements in my Cunning Chronograph -- a 60-pixel ring, a 24-pixel ring, and a 12-pixel ring.)   To be continued in Part 2
  • 热度 16
    2014-8-20 09:33
    1011 次阅读|
    0 个评论
    https://www.kernel.org/doc/Documentation/CodingStyle https://computing.llnl.gov/linux/slurm/coding_style.pdf 来自Linux之父Linus Torvals
  • 热度 15
    2014-2-20 17:45
    1703 次阅读|
    0 个评论
    According to this article and many others like it that cropped up recently, all kids should learn "coding" in elementary school. The argument usually claims that software is so important that everyone needs it to be productive citizens in the 21st century. By that argument, of course, we'd better teach them all molecular biology, electronic engineering, quantum mechanics, Chinese, and a hundred other subjects. Designing a curriculum means choosing, narrowing down the universe of subjects to those most important for a particular grade level. I salute any youngster who wants to learn coding or any other subject. But it's foolish to think everyone needs this skill. However, an educated, effective citizenry does need good reading skills. Basic math (at least). History. It's critical to learn to use a computer (though most kids get this at home), but designing one is much less important. From the article: "Coding teaches problem-solving, communication, and collaboration, Resnick says." Sure. And have you heard the old joke that an extroverted engineer is one whom looks at your shoes instead of his when talking to you? If coding teaches communication, why are engineers such famously poor communicators? Coding can teach problem solving. Ditto for math and the sciences. As does a carefully-taught English composition class. The latter will be of far more use to pretty much everyone than some misremembered Python syntax. Then there's the problem of confusing correlation with cause. I agree that engineers are good problem solvers. But is that because we learned to code/design? Or were we drawn to it because we are good problem solvers? Then there's this from The Huffington Post : "Coding is the new literacy... How are America's schools preparing youth for digital citizenship? Unfortunately, it remains focused on the 3Rs (reading, writing, arithmetic), while the ability to read, write, and manipulate code is quickly becoming more relevant." This argument, while trashing the three Rs, is simply incorrect. The ability to manipulate code is relevant only to that small segment of the population that needs to do so. The last thing we need is hordes of barely-competent Java people with no knowledge of software engineering tearing up a code base. As I write this, Code.orgs' welcome banner claims over 939,000,000 lines of code have been written by students. It's a meaningless metric. Perhaps they haven't mastered loops. Code.org is one of the few voices that carefully says they are not promoting coding per se; rather, they want the world to learn about computer science. Few others make such a distinction, and in talking to "civilians" over the years I feel most of them believe software engineering is all about sitting in front of a computer 8 hours a day writing code. One argument is that coding is fun (though I'd imagine only for a subset of kids) and that fun will translate into engineering as a career choice later in life. No doubt there's some truth there. Teach your kids about software, if they are interested. By all means form after-school coding clubs. Do mentor the young who are interested. But don't think coding is an educational or societal silver bullet. What's your take?  
  • 热度 19
    2013-5-26 20:44
    1605 次阅读|
    0 个评论
    fpga的设计流程,一般来说,文档的设计会占一半以上的时间,真正写RTL代码用的大概三分之一的时间,而剩下的时间则却全部用来做仿真测试;当然单纯的来讲,coding style并非固定的,每个公司甚至每一个人都有自己的写法,但就综合工具以及从代码的可读性以及可利用性来讲,良好的coding sytle 对于你的调试会有事半功倍的效果,从研究生到工作3年中,我始终坚持这种风格。接下来讨论一下具体的风格: 1:为了模拟DFF中的延时Tco,在module中会定义一个user delay,即`define UD #1,这仅仅是为了方便仿真而定义的,在RTL综合的时候会被自动优化掉; 2:一个module中只有一个clk信号,即每一个module内部的信号都是同步的;需要做跨时域处理的话在顶层操作,在顶层进行例化异步FIFO或者双口RAM; 3:组合逻辑与时序逻辑分开描述,组合逻辑用阻塞赋值,时序逻辑用非阻塞赋值,这基本上是coding style默认的; 4:为了便于仿真,便于调试,便于移植,便于共享等,强烈建议“一个always块只对一个信号进行赋值,而一个信号也只在一个always块里面进行赋值”;这样做的好处首先是仿真的时候信号出错便于定位而且便于修改,尤其是增加一个信号的时候修改的时候非常方便;其次可以避免你犯低级错误,多驱动源,latch的生成等等; 5:状态机的设计,当然建议用2段式或者3段式,而不建议用一段式,一段式可能看起来简单,但是当一个工程较为复杂的时候,你要在状态机中加入一个控制信号的时候会非常的不方便在不影响其他信号的前提下; 5:信号的命名规则: 这个非常重要,尤其是对于没有文档的设计来说,如果设计中的命名规则让人一看就大概知道这个信号的干什么的,就可以了,比如ADC_CS_B,B代表低电平有效,即ADC芯片的片选信号低电平有效,别人能从你的信号命名中获取一定的信息如下图所示:   6:clk与信号的输入输出 clk在顶层应该进入PLL模块然后在输出,为什么?增加驱动性能;而且要用全局时钟,输入域输出都用寄存器打一拍; 7:文档的重要性 稍微复杂的工程一定要有完备的文档描述,代码中也要有相应的注释;因为你的代码要做到别人能看懂,如果别人看你的代码有一头雾水的感觉,甚至不想看,感觉还不如自己写呢,这个就非常的失败,所以一定要养成这种良好的习惯; 总之,良好的coding style对设计非常重要,我在工作中深有体会,看到公司中那种随心所欲的代码真的头疼!!!!!!!!!!
相关资源