That's 300 kHz! It's too low. I wouldn't expect anything below 3 MHz to work.
There is a bottom limit on stable PLL operation. I don't know the details but basically the pre-DIVP VCO frequency is spec'd as 100 MHz minimum. You can go lower but jitter climbs very rapidly below 60 MHz.
If we take 60 MHz as the hard minimum of the VCO, and the largest DIVP following that is /30, so 2 MHz is the absolute minium the PLL can realistically do.
I think you can manually specifiy _clkmode. Though yea it probably is out-of-spec to run so slowly. Why would you want that, anyways? For low power consumption, there's RCSLOW mode.
@evanh ,
I have a blues application where I put the P2 in low power mode for an hour using RCSLOW.
void Sleep(int t)
{
int i;
i = _clkfreq;
//Slow speed low power mode
_clkset(_clkmode ^2, 20000);
sleep(t);
_clkset(_clkmode ^2, i);
}
I have an adafruit small LCD using an ST7789 chip through SPI that was not working and need to slow things down to see if it was a speed issue.
Sure enough it was.
@iseries said:
Is this suppose to work:
```
enum { _clkfreq = 300000 };
No, it is not supposed to work, and the similar Spin2 declarations produces an error ("PLL settings could not be achieved per _CLKFREQ") in PNut v43 as well. Looking at the PNut source code it appears that the minimum supported frequency is 3.3333 MHz. FlexProp has a slightly different calculation but I think comes out with the same minimum.
I'm not sure of the hardware limitation behind this, I just copied Chip's suggested clock settings calculation from a forum post.
I haven't used them so far but there are lots of type definitions like this in sample code for EtherCAT and libraries from Microchip. CAN packets have only 8 bytes of payload so people are extremely stingy with operand sizes. The generated code is quite efficient.
Just a suggestion for further optimization: (I don't really need it, I'm happy the way it is)
1. all WRLONGs except for the last could be optimized out.
2. setting of adjacent fields could be combined so that, for example, clearing all five fields could use one single ANDN
@ManAtWork said:
The generated code is quite efficient.
Not really
Just a suggestion for further optimization: (I don't really need it, I'm happy the way it is)
1. all WRLONGs except for the last could be optimized out.
2. setting of adjacent fields could be combined so that, for example, clearing all five fields could use one single ANDN
I don't think I ever got to enabling dead store optimization on fp. (Or did I? Try enabling optflags experimental and aggressive-mem...) Anyways, your main problem is that you're using a local variable and then taking the address of that somewhere in the function. Flexspin really doesn't like that and generates all those silly loads and stores through fp (though most of the loads get removed out as you can tell). You can use _builtin_alloca to acquire stack memory that you need to pass an address of into another function without triggering this local-on-stack behaviour.
All the AND(N)s would be merged if the stores weren't using the intermediate values.
... should work because the the initial declarations are empty and then replaced by the actual definitions. But all I get is lots of error messages from the compiler. So what is wrong?
(full source code attached)
... should work because the the initial declarations are empty and then replaced by the actual definitions. But all I get is lots of error messages from the compiler. So what is wrong?
(full source code attached)
This is why typedef struct is bad form. Write out the struct tag out everywhere:
Yes, C is confusing like that. Structs have their own namespace distinct from typedefs. If you write just typedef struct {} something, you're creating a struct without a name and typedef-ing that to something.
...doesn't work because I can't use the typedef before it's actually defined. I've read some hints on StackOverflow but I don't get it.
typedef means just that 'type define', you are defining a type (LinkedNode) as a unnamed struct, and since the type name is defined after the structure you can't use it to declare the members.
As others wrote, just give the struct a name and use it.
It is a common practice in these cases (maybe derived from the fact that early compilers can't assign the same name to the type) to name the structure as the type prefixed with an underscore.
To make things clear, you may separate the typedef from the structure definition:
Ok, thanks to everyone. I have to admit that I don't speak C as native language. I've learned programming with Modula and Oberon where everything is much more clear and unambigous. There's a reason why there are things like the "obfuscated C contest" and web pages like "why I hate C".
Even if typedef struct is said to be bad style I want to make clear that I intend to define a type here and not an instance.
And I have to apologize for abusing this thread, again. It has nothing to do with FlexSpin and works perfectly, now. (there were some other issues in the code like forgotten "this" left from the C++ port. But this was easy to fix now that the countless error messages went away)
@ManAtWork said:
Ok, thanks to everyone. I have to admit that I don't speak C as native language. I've learned programming with Modula and Oberon where everything is much more clear and unambigous. There's a reason why there are things like the "obfuscated C contest" and web pages like "why I hate C".
Even if typedef struct is said to be bad style I want to make clear that I intend to define a type here and not an instance.
And I have to apologize for abusing this thread, again. It has nothing to do with FlexSpin and works perfectly, now. (there were some other issues in the code like forgotten "this" left from the C++ port. But this was easy to fix now that the countless error messages went away)
struct LinkedNode { ... }; already makes it clear that you're defining a type and not an instance. It'd be rather pointless if the default were to define an instance.
A significant part of what makes C difficult is people taking the "easy" way and doing things like using typedef struct everywhere and trying to pretend the declaration-follows-use rule wasn't an integral part of the language by putting the star on the wrong side int* x;; I struggled with C types until I stopped doing these things. Many tutorials and style guides teach people to do things like this wrong in an attempt to provide a "gentle" introduction, but it only leads you off a cliff later on.
Also, if you didn't notice it, read the Linux Kernel Style Guide I linked to in an edit to my previous comment. It provides good rationales for most things, rather than just being a pile of arbitrary rules.
I started my programming learning with Fortran, at the university, as a student, using the punched cards, then 8-bit Atari Basic. And they said, who learned Basic, has his brain permanently damaged.
After that I learned Pascal.
In Pascal, you have
var p: ^integer
so more natural for me is int *x and I still don't understand what is the difference between these declarations (if any)
@pik33 said: int* xor int *x- that is the question.
I started my programming learning with Fortran, at the university, as a student, using the punched cards, then 8-bit Atari Basic. And they said, who learned Basic, has his brain permanently damaged.
After that I learned Pascal.
In Pascal, you have
var p: ^integer
so more natural for me is int *x and I still don't understand what is the difference between these declarations (if any)
That's why I use C only when I really have to.
There is no difference.
But if you define more than 1 variable on the same line, the second form is much more obvious:
There is no difference.
But if you define more than 1 variable on the same line, the second form is much more obvious:
int* x, y;
int *x, y;
x is a pointer to an int, while y is just an int.
Yes. The compiler doesn't care about whitespace; you can horribly misformat your code any way you like and it will compile just the same. But since the syntax rules of C say that the star binds to the variable name and not the type name, you should put it next to the variable name. As I said before, this is all explained by the "declaration follows use" rule: if you declare int *x[4], y(int z); and later write *x[1] or (*y)(2), the result has type int (i.e. x is an array of pointers to ints, and y is a pointer to a function taking an int and returning an int). (But please never declare both of those things on the same line.)
On the other hand, there are languages such as Go where the star binds to the type name; in these languages, you put the star next to the type.
Eric,
Is there a simple/proper way to substitute the sdmm.cc file without actually writing to the includes directories?
Also, is there support for multiple concurrent physical devices? ie: A second SD card slot at different pins. Being able to copy between them for example.
EDIT: I guess the answer to second question is yes. Something like ...
@evanh
The simplest way is to create a new folder in filesys with your code and then in vfs.h create a new command that points to that folder
I have my own version of the sd card functions with this function added to the vfs.h
/**
* @brief mount SD card for processing
* @param drive volume number of drive 0/1
* @param cs - chip select pin
* @param clk - clock pin
* @param mosi - master out slave in pin
* @param miso - master in slave out pin
* @return vfs - pointer to a vfs file structure
*/
vfs_t *_vfs_open_sdm(int drive, int cs, int clk, int mosi, int miso) _IMPL("filesys/fatfsm/filesystem.c");
Thanks Mike, that should do the job better than I was envisaging ... oh, that's not a direct replacement of sdmm.cc, I got some reading ahead of me ...
Execute task s=12
Read SDO ok
ReadSdo=12
DevName=IHSV57/60-EC
(The first two lines are printed by ReadSdo() internally to make sure it returns the correct number)
However, if I place the function call directly inside the printf brackets like this
Execute task s=12
Read SDO ok
12
DevName=IHSV57/60-EC
The format string "ReadSdo=%d\n" gets reduced to "%d\n" somehow or a carriage return is inserted but strangely without a line feed.
Posting the complete code doesn't make sense as it requires special hardware to execute. If nobody has a plausible explanation why this should happen (me messing up C, again) I'll try to figure out what's going on in the generated pasm code...
I think it has something to do with the fact that I call printf() from more than one cog. I think they should happen strictly in sequence and not concurrently because the client cog always waits for the server/driver cog to complete a command before doing the next step. But anyway, some of the characters in the buffer are swallowed.
IIRC that has to do with how flexspin attempts to avoid linking in the full dynamic printf implementation (awful and slow) by parsing the format string at compile time and generating hardcoded formatting calls instead. Having a function print while in a printf argument list causes some problem. I think you can use fprintf with stdout if you really want to, but that will link in all the bloatware.
I think I have to write my own debugging output functions, anyway. I just encounter some awful race conditions where everything works perfectly as long as there is enough delay caused by the printf()s and everything doesn't as soon as I remove them.
It has to run damn fast so all parsing and serial communication has to be avoided alltogether. I think I'll implement some hardcoded functions that take a pointer to a string, zero to four integer arguments or a pointer and size for a memory dump. This is written to a large buffer like a logfile in RAM. After I have detected a fault condition the whole buffer is parsed and the output formatted and transferred over the serial port.
Comments
@ersmith Thanks! Maybe I'll get the award for finding the last bug in the Spin2 compiler?
Is this suppose to work:
I get this error:
I have one of those odd frequency P2 and I have a project that needs to run really slooowww.
I know the answer is 63, 0 (19200000/64*1=300000)
There are a bunch of other frequencies that don't work as well.
Mike
That's 300 kHz! It's too low. I wouldn't expect anything below 3 MHz to work.
There is a bottom limit on stable PLL operation. I don't know the details but basically the pre-DIVP VCO frequency is spec'd as 100 MHz minimum. You can go lower but jitter climbs very rapidly below 60 MHz.
If we take 60 MHz as the hard minimum of the VCO, and the largest DIVP following that is /30, so 2 MHz is the absolute minium the PLL can realistically do.
I think you can manually specifiy
_clkmode
. Though yea it probably is out-of-spec to run so slowly. Why would you want that, anyways? For low power consumption, there's RCSLOW mode.Is RCSLOW not an option? It also has the advantage of stopping the crystal oscillator for even lower power.
On that note, here's my code for doing exactly that.
Mike,
You'll need to edit the coded limits in there but it should provide you with the tools to runtime adjust where the compile time won't go.
@evanh ,
I have a blues application where I put the P2 in low power mode for an hour using RCSLOW.
I have an adafruit small LCD using an ST7789 chip through SPI that was not working and need to slow things down to see if it was a speed issue.
Sure enough it was.
Mike
You just wanted to slow down the SPI clock?
No, it is not supposed to work, and the similar Spin2 declarations produces an error ("PLL settings could not be achieved per _CLKFREQ") in PNut v43 as well. Looking at the PNut source code it appears that the minimum supported frequency is 3.3333 MHz. FlexProp has a slightly different calculation but I think comes out with the same minimum.
I'm not sure of the hardware limitation behind this, I just copied Chip's suggested clock settings calculation from a forum post.
To my surprise I just found out that FlexC supports packed bit fields like this:
I haven't used them so far but there are lots of type definitions like this in sample code for EtherCAT and libraries from Microchip. CAN packets have only 8 bytes of payload so people are extremely stingy with operand sizes. The generated code is quite efficient.
translates to
Just a suggestion for further optimization: (I don't really need it, I'm happy the way it is)
1. all WRLONGs except for the last could be optimized out.
2. setting of adjacent fields could be combined so that, for example, clearing all five fields could use one single ANDN
Not really
I don't think I ever got to enabling dead store optimization on fp. (Or did I? Try enabling optflags
experimental
andaggressive-mem
...) Anyways, your main problem is that you're using a local variable and then taking the address of that somewhere in the function. Flexspin really doesn't like that and generates all those silly loads and stores throughfp
(though most of the loads get removed out as you can tell). You can use_builtin_alloca
to acquire stack memory that you need to pass an address of into another function without triggering this local-on-stack behaviour.All the AND(N)s would be merged if the stores weren't using the intermediate values.
I'm puzzled by C, again. What is the correct way to do a forward declaration of a pointer to a struct?
...doesn't work because I can't use the typedef before it's actually defined. I've read some hints on StackOverflow but I don't get it.
or
... should work because the the initial declarations are empty and then replaced by the actual definitions. But all I get is lots of error messages from the compiler. So what is wrong?
(full source code attached)
This is why
typedef struct
is bad form. Write out thestruct
tag out everywhere:EDIT: https://www.kernel.org/doc/html/latest/process/coding-style.html
Yes, C is confusing like that. Structs have their own namespace distinct from typedefs. If you write just
typedef struct {} something
, you're creating a struct without a name and typedef-ing that tosomething
.typedef struct thing gets me too, seems it just defines a potential structure.
You create an instance of it like this:
i2c_Port I2C1;
Not sure what purpose "I2C_Port" (with capitalized I2C) serves...
As explained above, that's the actual name of the struct. You could use it as
struct I2C_Port I2C1;
.typedef means just that 'type define', you are defining a type (LinkedNode) as a unnamed struct, and since the type name is defined after the structure you can't use it to declare the members.
As others wrote, just give the struct a name and use it.
It is a common practice in these cases (maybe derived from the fact that early compilers can't assign the same name to the type) to name the structure as the type prefixed with an underscore.
To make things clear, you may separate the typedef from the structure definition:
Means that you can create an instance also with it:
struct I2C_Port I2C1;
Is perfectly equal.The type is a short for 'struct ...'.
Ok, thanks to everyone. I have to admit that I don't speak C as native language. I've learned programming with Modula and Oberon where everything is much more clear and unambigous. There's a reason why there are things like the "obfuscated C contest" and web pages like "why I hate C".
I've chosen Macca's first version.
Even if
typedef struct
is said to be bad style I want to make clear that I intend to define a type here and not an instance.And I have to apologize for abusing this thread, again. It has nothing to do with FlexSpin and works perfectly, now. (there were some other issues in the code like forgotten "this" left from the C++ port. But this was easy to fix now that the countless error messages went away)
struct LinkedNode { ... };
already makes it clear that you're defining a type and not an instance. It'd be rather pointless if the default were to define an instance.A significant part of what makes C difficult is people taking the "easy" way and doing things like using
typedef struct
everywhere and trying to pretend the declaration-follows-use rule wasn't an integral part of the language by putting the star on the wrong sideint* x;
; I struggled with C types until I stopped doing these things. Many tutorials and style guides teach people to do things like this wrong in an attempt to provide a "gentle" introduction, but it only leads you off a cliff later on.Also, if you didn't notice it, read the Linux Kernel Style Guide I linked to in an edit to my previous comment. It provides good rationales for most things, rather than just being a pile of arbitrary rules.
int* x
orint *x
- that is the question.I started my programming learning with Fortran, at the university, as a student, using the punched cards, then 8-bit Atari Basic. And they said, who learned Basic, has his brain permanently damaged.
After that I learned Pascal.
In Pascal, you have
var p: ^integer
so more natural for me is
int *x
and I still don't understand what is the difference between these declarations (if any)That's why I use C only when I really have to.
There is no difference.
But if you define more than 1 variable on the same line, the second form is much more obvious:
x is a pointer to an int, while y is just an int.
Yes. The compiler doesn't care about whitespace; you can horribly misformat your code any way you like and it will compile just the same. But since the syntax rules of C say that the star binds to the variable name and not the type name, you should put it next to the variable name. As I said before, this is all explained by the "declaration follows use" rule: if you declare
int *x[4], y(int z);
and later write*x[1]
or(*y)(2)
, the result has typeint
(i.e.x
is an array of pointers to ints, andy
is a pointer to a function taking anint
and returning anint
). (But please never declare both of those things on the same line.)On the other hand, there are languages such as Go where the star binds to the type name; in these languages, you put the star next to the type.
Eric,
Is there a simple/proper way to substitute the
sdmm.cc
file without actually writing to the includes directories?Also, is there support for multiple concurrent physical devices? ie: A second SD card slot at different pins. Being able to copy between them for example.
EDIT: I guess the answer to second question is yes. Something like ...
@evanh
The simplest way is to create a new folder in filesys with your code and then in vfs.h create a new command that points to that folder
I have my own version of the sd card functions with this function added to the vfs.h
Mike
Thanks Mike, that should do the job better than I was envisaging ... oh, that's not a direct replacement of sdmm.cc, I got some reading ahead of me ...
Today I'm getting some really strange behaviour. I hope it's not me stepping into another C pitfall...
executes correctly and prints out
(The first two lines are printed by ReadSdo() internally to make sure it returns the correct number)
However, if I place the function call directly inside the printf brackets like this
I get this:
The format string "ReadSdo=%d\n" gets reduced to "%d\n" somehow or a carriage return is inserted but strangely without a line feed.
Posting the complete code doesn't make sense as it requires special hardware to execute. If nobody has a plausible explanation why this should happen (me messing up C, again) I'll try to figure out what's going on in the generated pasm code...
Stack or heap overflow maybe. Is this running on a second cog?
I think it has something to do with the fact that I call printf() from more than one cog. I think they should happen strictly in sequence and not concurrently because the client cog always waits for the server/driver cog to complete a command before doing the next step. But anyway, some of the characters in the buffer are swallowed.
IIRC that has to do with how flexspin attempts to avoid linking in the full dynamic printf implementation (awful and slow) by parsing the format string at compile time and generating hardcoded formatting calls instead. Having a function print while in a printf argument list causes some problem. I think you can use fprintf with stdout if you really want to, but that will link in all the bloatware.
I think I have to write my own debugging output functions, anyway. I just encounter some awful race conditions where everything works perfectly as long as there is enough delay caused by the printf()s and everything doesn't as soon as I remove them.
It has to run damn fast so all parsing and serial communication has to be avoided alltogether. I think I'll implement some hardcoded functions that take a pointer to a string, zero to four integer arguments or a pointer and size for a memory dump. This is written to a large buffer like a logfile in RAM. After I have detected a fault condition the whole buffer is parsed and the output formatted and transferred over the serial port.