can't SLEEP() for worrying - Page 1
Forum section: electronics / general

author: PerranOak
author_rank: Frequent Contributor
timestamp: March 16, 2021, 05:08:53 pm
content: I have a 12F683 hooked-up to a 74HC595 (circuit attached) and this simple programme (relevant parts):Code:#define data GPIObits.GP0#define clock GPIObits.GP1void main(void){int display = 7;for (int count = 0; count <8; count++){data = (display >> count) & 1; //right shifts by 0,1,2,3.. then blanks all but bit0clock = 1; //clock pulse onclock = 0; //clock pulse off}clock = 1; //Final pulse that RCLK is expecting asclock = 0; // it is one pulse behind SRCLK.__delay_ms(2000);//SLEEP();}Like it is here, the prog works fine and displays the number 7 on the LEDs.It does flicker though which surprised me as I thought it would run through once then stop but it seems to repeat like there was a while command?Anyway, that's not why I rang. When I comment-out the__delayand "un-comment-out" theSLEEP()all LEDs are off. It seems to be in sleep mode because theCLKOUTshows no clock.I expected that the 7 would be displayed, the uC would go to sleep and the LEDs would remain on.I am obviously doing something wrong. Any advice would be most welcome, thank you.N.B.Please assume that the appropriate connects to ground, Vcc and required resistors are made - left out for clarity.

author: MikeK
author_rank: Super Contributor
timestamp: March 16, 2021, 06:10:03 pm
content: How long do you think it takes to get to the Sleep() command?

author: ajb
author_rank: Super Contributor
timestamp: March 16, 2021, 07:46:04 pm
content: Quote from: PerranOak on March 16, 2021, 05:08:53 pmI know this isn't your main question, but this is because your main function is exiting. On a computer application this may be fine, because then execution will return to the desktop/command line/whatever, but on an MCU there's no place to exit to! So your application completes main, and then probably just runs through the rest of the program memory (which hopefully has been erased to something equivalent to NOP or some invalid instruction that won't do any harm), and then runs right back to the beginning when the program counter overflows. This is why you always see a `while(1){ }` block in embedded main functions, because you want the application to stay there forever. In the case of your test program here, where you truly want it to only execute once, you can simply put a `while(1);` statement at the end which will cause the MCU to just spin there forever.The sleep problem may depend on the sleep configuration. What does the datasheet see about what peripherals are active in sleep? There may be multiple sleep levels as well, and it may be possible/necessary to configure individual peripherals for operation during sleep.

author: DavidAlfa
author_rank: Super Contributor
timestamp: March 16, 2021, 09:54:25 pm
content: As they already told you, the main function MUST be a loop.What you're doing is undefined behavior. If there's more code after the main end address (initialization, whatever), it will inmediately excecute it.Or skip everything until it reaches the end of the flash, causing a reset (hence the flickering you see).If you want to stop forever at some point, then use while(1).Something like this:Code:#definedataGPIObits.GP0#defineclockGPIObits.GP1#definerepeat_val(unsigned long)500000// Value to use as a timer. Adjust as you need for longer or shorter timevoid main(void){unsigned char display = 7;// Digit to display. Better to use char (int is 16 bit, slower on 8bit PIC12), as you can only display 0x0-0xF digits (0-15 decimal)unsigned long tim = 0;// Huge 32bit variable to use as a timer (Better to use a real timer)while(1){// Foreverfor (int count = 0; count <8; count++) {// Update displaydata = (display >> count) & 1;// Right shifts by 0,1,2,3.. then blanks all but bit0clock = 1;// Clock pulse onclock = 0;// Clock pulse off}clock = 1;// Final pulse that RCLK is expecting asclock = 0;// it is one pulse behind SRCLK.if(++tim>repeat_val){// Increase value. If reached limit:tim=0;// Reset variableasm("sleep");// Sleep (CPU stops here)//sleep();// I think this worked too...// When it wakes up, it will repeat the cycle (You need to enable some event to wake up. Like an external input, a timer...)}while(1);// If at some point you want to stop the CPU forever, do this.// This program code will never reach this, as it's locked inside the previous while(1).}}

author: DrG
author_rank: Super Contributor
timestamp: March 16, 2021, 10:25:49 pm
content: Quote from: DavidAlfa on March 16, 2021, 09:54:25 pmI hope I am not being too nit-picky here but I don't think that the behavior is undefined. I think that the program termination is implementation specific (and that is right out of some standard or other). We know that main() was intended to return from whatever called it, but 8 pin pics were not what they had in mind.It makes a point because he could look at the asm list and find out where it goes. Empirically, it goes to some start up code and executes again - he is seeing that when he gets a flicker.Now, what happens when he does a sleep()? I *think* on that PIC it will compile to load the PC with the next instruction, because that is where it can pick up again, unless it comes out of sleep with a reset. But, because it the last program instruction, I have no idea what it is loading - I have seen people add NOPs in that situation, the asm listing should provide the information.There are no configuration lines so I don't even know if it is waking up at all (like a WDT TO), in which case, I don't see why the GPIO is getting messed up. But for the reasons already mentioned by you and others, I would only wonder if the OP is just using sleep() instead of while(1) or goto here (which I admit to using something if I am debugging).In fact, I don't even know if he is using xc8 or ??In any event, there is something very basic to fix as already noted.

author: DavidAlfa
author_rank: Super Contributor
timestamp: March 16, 2021, 11:25:57 pm
content: You made me doubt. So I tried.In STM32, it returns to the init...but after that it jumps to a random address, It changes depending on the flash contents , ex if you add a nop in the main, 2 nops...So far, if it didn't cause a hard fault instantly, it jumped to the middle of a timer or a gpio routine, then causing a hard fault.From what I remember, basic pics just reset themselves ... I will have to remove the dust from my pickit3

author: ajb
author_rank: Super Contributor
timestamp: March 17, 2021, 02:21:51 am
content: The effect of a PC wraparound will depend on the architecture. A lot of architectures put the vector table at the beginning of memory, but how it's stored varies. I think in AVRs, it's a table of jump instructions to the ISR locations, and the first one is the reset vector, so the mcu can just immediately start executing with PC=0, therefore wraparound (or jump to that location) will then jump straight to the reset handler just like when the chip starts up normally. ARMs store the vector table as a list of addresses, the first one being the initial stack pointer, which the core loads to the SP register at startup before jumping to the reset handler which is the second address in the table, so attempting to execute from the beginning of memory will depend on what, if any, instructions the addresses in the vector table resemble. I'm not very familiar with PICs and couldn't immediately find an answer on how their vector tables work.Of course this is only applicable if the mcu manages to run to the end of memory; it may well crash first, or in the case of something like an ARM end up in a fault handler when it tries to execute an invalid instruction or load an invalid address, which may result in a reset depending on what sort of fault handler is present. Or it could end up in a ROM bootloader if one is present. So best to simply not let your main function exit 😛

author: Renate
author_rank: Super Contributor
timestamp: March 27, 2021, 08:26:29 pm
content: In AVR8 land:Code:5e6:0e 94 ec 0ccall0x19d8; 0x19d8 <main>5ea:0c 94 20 0djmp0x1a40; 0x1a40 <_exit>00001a40 <_exit>:1a40:f8 94cli00001a42 <__stop_program>:1a42:ff cfrjmp.-2; 0x1a42 <__stop_program>So, if main ever returns it turns off interrupts and jumps into a tight loop.

author: DavidAlfa
author_rank: Super Contributor
timestamp: March 27, 2021, 11:47:04 pm
content: Anyways, who and why did ever returned from main() in a MCU? Not regarding any RTOS.