@@ -378,6 +378,15 @@ impl EntryInterruptEnable {
378378/// `#[interrupt] fn DefaultHandler(..` can be used to override the default interrupt handler. When 
379379/// not overridden `DefaultHandler` defaults to an infinite loop. 
380380/// 
381+ /// `#[interrupt(wake_cpu)]` additionally returns the CPU to active mode after the interrupt 
382+ /// returns. This cannot be done by naively writing to the status register, as the status register 
383+ /// contents are pushed to the stack before an interrupt begins and this value is loaded back into 
384+ /// the status register after an interrupt completes, effectively making any changes to the status 
385+ /// register within an interrupt temporary. 
386+ /// Using the `wake_cpu` variant incurs a delay of two instructions (6 cycles) before the interrupt 
387+ /// handler begins. 
388+ /// The following status register bits are cleared: SCG1, SCG0, OSC_OFF and CPU_OFF. 
389+ /// 
381390/// # Properties 
382391/// 
383392/// Interrupts handlers can only be called by the hardware. Other parts of the program can't refer 
@@ -417,11 +426,21 @@ impl EntryInterruptEnable {
417426pub  fn  interrupt ( args :  TokenStream ,  input :  TokenStream )  -> TokenStream  { 
418427    let  f:  ItemFn  = syn:: parse ( input) . expect ( "`#[interrupt]` must be applied to a function" ) ; 
419428
420-     if  !args. is_empty ( )  { 
421-         return  parse:: Error :: new ( Span :: call_site ( ) ,  "this attribute accepts no arguments" ) 
429+     let  maybe_arg = parse_macro_input:: parse :: < Option < Ident > > ( args. clone ( ) ) ; 
430+ 
431+     let  wake_cpu = match  maybe_arg { 
432+         Ok ( None )  => false , 
433+         Ok ( Some ( ident) )  if  ident == "wake_cpu"  => true , 
434+         Ok ( Some ( _) )  => { 
435+             return  parse:: Error :: new ( 
436+                 Span :: call_site ( ) , 
437+                 "this attribute accepts only 'wake_cpu' as an argument" , 
438+             ) 
422439            . to_compile_error ( ) 
423-             . into ( ) ; 
424-     } 
440+             . into ( ) 
441+         } 
442+         Err ( e)  => return  e. into_compile_error ( ) . into ( ) , 
443+     } ; 
425444
426445    let  fspan = f. sig . span ( ) ; 
427446    let  ident = f. sig . ident ; 
@@ -491,21 +510,46 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
491510        let  output = f. sig . output ; 
492511        let  hash = random_ident ( ) ; 
493512        let  ident = ident. to_string ( ) ; 
494-         quote ! ( 
495-             #[ export_name = #ident] 
496-             #( #attrs) * 
497-             #unsafety extern "msp430-interrupt"  fn  #hash( )  { 
498-                 #check
499- 
500-                 #[ inline( always) ] 
501-                 #unsafety fn  #hash<' a>( #fn_param)  #output { 
502-                     #( #vars) * 
503-                     #( #stmts) * 
513+         if  wake_cpu { 
514+             quote ! ( 
515+                 #[ export_name = #ident] 
516+                 #( #attrs) * 
517+                 #[ unsafe ( naked) ] 
518+                 unsafe  extern "msp430-interrupt"  fn  #hash( )  { 
519+                     #[ inline( always) ] 
520+                     #unsafety extern "msp430-interrupt"  fn  #hash<' a>( #fn_param)  #output { 
521+                         #check
522+                         #( #vars) * 
523+                         #( #stmts) * 
524+                     } 
525+                     { 
526+                         // Clear SCG1, SCG0, OSC_OFF, CPU_OFF in saved copy of SR register on stack 
527+                         const  MASK :  u8  = ( 1 <<7 )  + ( 1 <<6 )  + ( 1 <<5 )  + ( 1 <<4 ) ; 
528+                         core:: arch:: naked_asm!( 
529+                             "bic.b #{mask}, 0(r1)" , 
530+                             "jmp {inner}" , 
531+                             inner = sym #hash, 
532+                             mask = const  MASK 
533+                         ) ; 
534+                     } 
504535                } 
505-                 {  #hash( #fn_arg)  } 
506-             } 
507-         ) 
508-         . into ( ) 
536+             ) 
537+         }  else  { 
538+             quote ! ( 
539+                 #[ export_name = #ident] 
540+                 #( #attrs) * 
541+                 #unsafety extern "msp430-interrupt"  fn  #hash( )  { 
542+                     #check
543+ 
544+                     #[ inline( always) ] 
545+                     #unsafety fn  #hash<' a>( #fn_param)  #output { 
546+                         #( #vars) * 
547+                         #( #stmts) * 
548+                     } 
549+                     {  #hash( #fn_arg)  } 
550+                 } 
551+             ) 
552+         } . into ( ) 
509553    }  else  { 
510554        parse:: Error :: new ( 
511555            fspan, 
0 commit comments