Attempting To Create Lean IO From The Simpletools Library
idbruce
Posts: 6,197
Hello Everyone
I am currently in the process of trying to trim some fat off of the simpletools library for IO.
I am now pretty much finished with what I want to do, but I am not exactly sure which includes I can delete. I could find the answer, by deleting them one by one and testing, but I am certain that one of you guys will know the answer. I know that propeller.h will have to stay, but what other files are an absolute necessity?
I am currently in the process of trying to trim some fat off of the simpletools library for IO.
I am now pretty much finished with what I want to do, but I am not exactly sure which includes I can delete. I could find the answer, by deleting them one by one and testing, but I am certain that one of you guys will know the answer. I know that propeller.h will have to stay, but what other files are an absolute necessity?
/** * @file lean_io.h * @contributor Bruce Drummond */ #ifndef LEAN_IO_H #define LEAN_IO_H #if defined(__cplusplus) extern "C" { #endif #include <propeller.h> /* #include "simpletext.h" #include <driver.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <cog.h> #include <ctype.h> #include <unistd.h> #include <sys/stat.h> #include <dirent.h> #include <sys/sd.h> #include <math.h> #include "simplei2c.h" */ /** * @author Andy Lindsay * @copyright Copyright (C) Parallax, Inc. 2014. See end of file for terms of use (MIT License). * @brief This library provides convenient functions * for a variety of microcontroller I/O * @details This library provides convenient I/O pin monitoring and control functions */ //////////////////////////////////////////////////////////////////////////////// /** * @brief Set an I/O pin to output-high * * @details This function set makes the Propeller * P8X32A connect the I/O pin to its positive 3.3 V * supply voltage enabling it to source up to * 40 mA of current (max 1 W dissipation per chip). * * @param pin Number of the I/O pin to set high. */ void high(int pin); /** * @brief Set an I/O pin to output-low * * @details This function makes the Propeller * P8X32A connect the I/O pin to its ground 0 V * supply voltage enabling it to sink up to * 40 mA of current (max 1 W dissipation per chip). * * @param pin Number of the I/O pin to set low. */ void low(int pin); /** * @brief Set an I/O pin to input and return 1 if pin * detects a high signal, or 0 if it detects low. * * @details This function makes the Propeller * connect the I/O pin to its input buffer * so that it can return the binary value of the * voltage applied by an external circuit. * * @param pin Number of the I/O pin to set to input. * * @returns 1 to indicate high (above 1.65 V) received * or 0 to indicate low (below 1.65 V) received. */ int input(int pin); /** * @brief Toggle the output state of the I/O pin. * * @details Change I/O pin's output state from low to high * or high to low. This function assumes that some other * function has already set the I/O pin to output. * * @param pin I/O pin number. * * @returns The new pin state. */ unsigned int toggle(int pin); /** * @brief Reverse the direction of an I/O pin. * * @details If an I/O pin's direction is set to input, this * function changes it to output. If it's set to output, * this function changes it to input. * * @param pin I/O pin number. * * @returns The new pin direction. */ unsigned int reverse(int pin); /** * @brief Check the state of an I/O pin without * setting it to input. * * @details Use this function instead of input if the * Propeller needs to maintain an output. For example, * you can use this to monitor another cog's or counter's * output signal activity on a pin. (Note: if the pin * is already set to input, it will return the state the * external circuit is applying, just like input.) * * @param pin Number of the I/O pin * * @returns The pin's state. If the pin is an output, * 1 = 3.3 V and 0 = 0 V. If the pin is an input, * 1 means V > 1.65 V, 0 means it's less. */ unsigned int get_state(int pin); /** * @brief Check the direction of the I/O pin. * * @details This function will tell you the direction of the * I/O pin as seen by the cog executing it. Keep in mind that * that your program might make other cogs use the I/O pin as * an output, and a cog that treats a pin as an output wins over * one that treats it as an input. * * @param pin I/O pin number * * @returns I/O pin direction as seen by the cog that runs the * function. */ unsigned int get_direction(int pin); /** * @brief Get I/O pin output state. * * @details Keep in mind that this function reports the value in the output * register for the cog running the function. That doesn't tell you if the * I/O pin is set to input, or whether another cog is sending a different * output state. * * @param pin I/O pin number. * * @returns In a register bit for I/O pin, either 1 or 0. */ unsigned int get_output(int pin); /** * @brief Set an I/O pin to a given direction. * * @details This function sets an I/O pin to either output or input. * * @param pin I/O pin number. * @param direction I/O pin direction. */ void set_direction(int pin, int direction); /** * @brief Set I/O pin output register bit to either 1 or 0. * * @details This function focuses on the I/O pin's output register. If you * intend to use it to send high or low signals, consider using high or low * functions. This function can also be used in conjunction with set_direction * to send high or low signals. * * @param pin I/O pin to set high or low. * @param state 1 for high, 0 for low (when pin is actually set to output, * which can be done with setDirection. */ void set_output(int pin, int state); /** * @brief Get states of a contiguous group of I/O pins * * @details This works the same as getState, but for a group of pins. It * tells you the actual state of each pin, regardless of whether it's a * voltage applied to input or transmitted by an output. * * @param endPin The highest numbered pin. * @param startPin The lowest numbered pin. * * @returns States value containing the binary bit pattern. The value for * startPin should be in bit-0, next in bit-1, etc. */ unsigned int get_states(int endPin, int startPin); /** * @brief Get directions for a contiguous group of I/O pins. * * @details Get direction register states from a contiguous group of bits * in the cog's output register. * * @param endPin The highest numbered pin. * @param startPin The lowest numbered pin. * * @returns States value containing a binary bit pattern. The value for * startPin should be in bit-0, next in bit-1, etc. */ unsigned int get_directions(int endPin, int startPin); /** * @brief Get output settings for a contiguous group of I/O pins. * * @details Get output register settings for a contiguous group of bits * in the cog's output register. * * @param endPin The highest numbered pin. * @param startPin The lowest numbered pin. * * @returns Pattern value containing a binary bit pattern. The value * for startPin should be in bit-0, next in bit-1, etc. */ unsigned int get_outputs(int endPin, int startPin); /** * @brief Set directions for a contiguous group of I/O pins. * * @details Set directions values in a contiguous group of bits in the * cog's output register. * * @param endPin The highest numbered pin. * @param startPin The lowest numbered pin. * @param pattern Value containing the binary bit pattern. The value for * startPin should be in bit-0, next in bit-1, etc. */ void set_directions(int endPin, int startPin, unsigned int pattern); /** * @brief Set output states for a contiguous group of I/O pins. * * @details Set output states of a contiguous group of bits in the cog's * output register. * * @param endPin The highest numbered pin. * @param startPin The lowest numbered pin. * @param pattern Value containing the binary bit pattern. The value for * startPin should be in bit-0, next in bit-1, etc. */ void set_outputs(int endPin, int startPin, unsigned int pattern); #if defined(__cplusplus) } #endif /* __cplusplus */ #endif /* LEAN_IO_H */ /** * TERMS OF USE: MIT License * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */
/* * @file lean_io.c * @contributor Bruce Drummond * @brief lean_io functions, without the overhead. These functions are identical to those of * the simpletools library. */ #include "lean_io.h" // lean_io function prototypes /* * @definition void low(int pin) * @original source low.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief low function source, see lean_io.h for documentation. */ void low(int pin) { int mask = 1 << pin; // Set up mask OUTA &= ~mask; // Pin output state to low DIRA |= mask; // Pin direction to output } /* * @definition void high(int pin) * @original source high.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief high function source, see lean_io.h for documentation. */ void high(int pin) { int mask = 1 << pin; // Set up mask OUTA |= mask; // Bitwise OR w/ OUTA & DIRA DIRA |= mask; } /* * @definition int input(int pin) * @original source input.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief input function source, see lean_io.h for documentation. */ int input(int pin) { int mask = 1 << pin; // Set up mask DIRA &= ~mask; // AND DIRA with NOT mask return (INA & mask) >> pin; // Return input state } /* * @definition unsigned int toggle(int pin) * @original source toggle.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief toggle function source, see lean_io.h for documentation. */ unsigned int toggle(int pin) { int mask = 1 << pin; OUTA ^= mask; return (OUTA >> pin) & 1; } /* * @definition unsigned int reverse(int pin) * @original source reverse.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief reverse function source, see lean_io.h for documentation. */ unsigned int reverse(int pin) { unsigned int mask = 1 << pin; // Set up mask DIRA ^= mask; // XOR direction reg wi mask return (DIRA >> pin) & 1; // Return current direction } /* * @definition unsigned int get_state(int pin) * @original source getState.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief getState function source, see lean_io.h for documentation. */ unsigned int get_state(int pin) { unsigned int pinstate = INA; // Copy INA return (pinstate >> pin) & 1; // Shift right, mask, return } /* * @definition unsigned int get_states(int endPin, int startPin) * @original source getstates.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief getStates function source, see lean_io.h for documentation. */ unsigned int get_states(int endPin, int startPin) { unsigned int pattern = INA; // Copy INA if(endPin < startPin) // Handle reverse pin size { int temp = startPin; startPin = endPin; endPin = temp; } pattern <<= (31 - endPin); // Remove zeros to left pattern >>= (31 - endPin + startPin); // Right justify & return return pattern; // Right justify & return } /* * @definition unsigned int get_direction(int pin) * @original source getDirection.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief getDirection function source, see lean_io.h for documentation. */ unsigned int get_direction(int pin) { unsigned int pindir = DIRA; // Copy of OUTA register return (pindir >> pin) & 1; // Shift right and mask } /* * @definition unsigned int get_directions(int endPin, int startPin) * @original source getDirections.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief getDirections function source, see lean_io.h for documentation. */ unsigned int get_directions(int endPin, int startPin) { unsigned int pattern = DIRA; // Copy INA if(endPin < startPin) // Handle reverse pin size { int temp = startPin; startPin = endPin; endPin = temp; } pattern <<= (31 - endPin); // Remove zeros to left pattern >>= (31 - endPin + startPin); // Right justify & return return pattern ; // Right justify & return } /* * @definition unsigned int get_output(int pin) * @original source getOutput.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief getOutput function source, see lean_io.h for documentation. */ unsigned int get_output(int pin) { return (OUTA >> pin) & 1; // Return OUTA shifted rt & masked } /* * @definition unsigned int get_outputs(int endPin, int startPin) * @original source getOutputs.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief getOutputs function source, see lean_io.h for documentation. */ unsigned int get_outputs(int endPin, int startPin) { unsigned int pattern = OUTA; // Copy OUTA if(endPin < startPin) { int temp = startPin; startPin = endPin; endPin = temp; } pattern <<= (31 - endPin); // Remove values to left pattern >>= (31 - endPin + startPin); // Shift right & return return pattern; } /* * @definition void set_direction(int pin, int direction) * @original source setDirection.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief setDirection function source, see lean_io.h for documentation. */ void set_direction(int pin, int direction) { unsigned int mask = 1 << pin; if (direction == 0) { DIRA &= (~mask); } else { DIRA |= mask; } } /* * @definition void set_directions(int endPin, int startPin, unsigned int pattern) * @original source setDirections.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief setDirections function source, see lean_io.h for documentation. */ void set_directions(int endPin, int startPin, unsigned int pattern) { if(endPin < startPin) // Handle reverse pin size { int temp = startPin; startPin = endPin; endPin = temp; } unsigned int andMask = -1; andMask <<= (31 - (endPin-startPin)); andMask >>= (31 - endPin); andMask = ~andMask; unsigned int orMask = pattern << (startPin); DIRA = (DIRA & andMask) | orMask; } /* * @definition void set_output(int pin, int state) * @original source setOutput.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief setOutput function source, see lean_io.h for documentation. */ void set_output(int pin, int state) { unsigned int mask = 1 << pin; if(state == 0) { OUTA &= (~mask); } else { OUTA |= mask; } } /* * @definition void set_outputs(int endPin, int startPin, unsigned int pattern) * @original source setOutputs.c * @author Andy Lindsay * @version 0.85 * @copyright Copyright (C) Parallax, Inc. 2012. See end of file for terms of use (MIT License). * @brief setOutputs function source, see lean_io.h for documentation. */ void set_outputs(int endPin, int startPin, unsigned int pattern) { if(endPin < startPin) // Handle reverse pin size { int temp = startPin; startPin = endPin; endPin = temp; } unsigned int andMask = -1; andMask <<= (31 - (endPin-startPin)); andMask >>= (31 - endPin); andMask = ~andMask; unsigned int orMask = pattern << (startPin); OUTA = (OUTA & andMask) | orMask; } /** * TERMS OF USE: MIT License * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */
Comments
And in theory, if you leave all your includes in, they'll get striped from the binary with --gc-sections by the linker. So it shouldn't matter anyway.
I was thinking that there might be a difference between compiling and actually being fully functional.
I have not yet researched compiler and linker settings, or what they do.
Normally if you use a function from a C file the entire code content of the file gets added to your program. Hence the need for the options mentioned above.
However I'm not sure what happens with the simple*.h files. Perhaps the are actual functions in there. tut-tut.
The files compile with just propeller.h. So later today, I will test the input and output functions, and then I will compare it with the same tests using simpletools. That should tell me if this was worthwhile or a waste of time.
I did use the word "Attempting" in the title
I will have to examine these results much closer to find out why.
Okay here is the result of a test.
TestLean.c source:
Build Status pane:
Result: Code Size 2,636(2,804 Total)
HelloMessage.c source:
Build Status pane:
Result: Code Size 2,268(2,436 Total)
All of the functions contained within lean_io.c, were initially all in seperate files. Referring to what Heater said, I am almost inclined to believe that the size increase is due to the fact that I included all of those functions into one file.
It might explain some of what you've experienced.
Thank you for pointing out that tutorial, because I never knew that. Throughout the years, I have always thought that it was the includes that increased the program size, and that the includes, included the source into the program.
Just goes to show you how wrong old Brucie boy can be
And so much for trimming the fat.....
yeah. Funny that includes do not include. The C/C++ thing.
If you add --gc-sections to the cmd line you might get smaller. @swimdude did some experiments with this. There is something else like --gc-functions or --gc-section-functions(?) or so. Sorry to be vague, I just read @swimdudes posts about this. I never used C/C++ on the prop besides some testing with Catalina and PropGCC.
Not that I dislike C/C++. It's just that I never had a job needing me to program C/C++. So besides playing around with it I never used C/C++ seriously.
Without them cmd line switches GCC will just prune out unused FILES not FUNCTIONS.
As stated before by @Heater. the full source of the C/C++ file will be compiled, even if the file contains unused functions. GCC does just prune files by default. Putting all in one file disables that.
Like Prop Tool it compiles all of it and the binary is bigger. BST is smarter there and has the option to remove unused functions/methods in Spin source. I really wish @Roy would implement this in OpenSpin.
But if you enable function pruning in PropGCC it does it, even if all source is in one file.
May someone chime in on the syntax for it. I just remember reading posts about it.
Enjoy!
Mike
Thanks for your input.
I had put off the GCC for several years, but now that I am messing around with C/C++ to work on the prop, I am starting to get into it. In a couple more minutes, I will be posting an archive to the Teacup port thread, which contains the port project. Not that it is without problems, because there are quite a few, but a large portion of the Teacup files, now complie for use on the Propeller
As a word of friendly advice, take the time to experiment.
From PropWare's CMake configuration:
Every call to every GCC command should include "-ffunction-sections -fdata-sections"
and every call to the linker should include "-Wl,--gc-sections".
Here's the breakdown:
-f<stuff> - <stuff> is a flag
function-sections - Make every function its own section (as opposed to one section for the whole file)
data-sections - Make every `data` (aka, global variables) its own section
-Wl,<stuff> - <stuff> should only be passed to the linker, not the compiler (useful when invoking the linker via "gcc" instead of "ld")
--gc-sections - prune all unused sections
When comparing simpletools against lean_io, in SimpleIDE and in a similar test to the one above, but with pruning enabled, the resulting sizes are equal.
I can live with that.
I like the idea of all the functions being there, where you can see the definition. So I will probably use lean_io, when I do not need the full functionality of simpletools.
I meant to test that earlier, but your post pushed me over the edge Thanks.