write once register issue

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

write once register issue

Jump to solution
3,765 Views
100asong
Contributor I

Hi,Dear All

 

      My cpu is MC9S12XEP100.

 

      CLKSEL &= ~0xFC;            // clear CLKSEL Register

     This sentence  write bit CLKSEL_COPWAI,this means that I can't write CLKSEL_COPWAI again since it is write once register in Normal Mode.

      Whether I can use " CLKSEL = 0x00" sentence in the subsequent code?It will affect CLKSEL_COPWAI?

Labels (1)
0 Kudos
Reply
1 Solution
2,338 Views
kef
Specialist I

Write once bit doesn't mean you must do all your best limiting write accesses to write once bit. You may write to write once bit as many times as you wish, but only first write is accepted.

 

For exmple

1) default CANE bit state after reset is "0". 

2) First write to CAN0CTL1 with "1" in CANE bit position succeeds. "1" is locked to CANE bit. You may confirm that reading CAN0CTL1.

3) Second write to CAN0CTL1 with "0" in CANE bit position doesn't succeed, because this is second write to CAN0CTL1. Though you write "0" to CANE, you will read CANE==1.

 

Another example

1) default CANE bit state after reset is "0". 

2) First write to CAN0CTL1 with CANE=0 doesn't change state of CANE bit, but "0" is still locked to CANE.

3) You want to enable CAN module and write CANE=1 to CAN0CTL1, but wirte fails because CANE is already locked in CANE==0 state. You won't be able to enable CAN module in this case.

 

 

So to enable CAN you must only provide that first write to CAN0CTL1 is writing "1" to CANE bit. You need CAN enabled, so both, bootloader and application should not fail if CANE==1 before any of two canInit() routines.

 

To reconfigure CAN, you should switch from running mode to initialization mode by writing "1" to INITRQ bit. Both your CAN init routines are doing that.

 

 

View solution in original post

0 Kudos
Reply
8 Replies
2,338 Views
kef
Specialist I

Write once is triggered by any write to register. In particular register you can't write only bits you want, you write them all at once. Even BRSET and BRCLR instructions write access whole registers, not single or couple of bits you want, but always all 8 bits.

0 Kudos
Reply
2,338 Views
100asong
Contributor I

Dear Kef,

     

      Thanks for reply.

   

      I write bootloader code meet this thing:Bootloader uses can and application uses also CAN.So CAN0CTL1_CANE need to been set at bootloader part and application part.MCU runs  Bootloader and then run App.

      In BDM mode,it will okay.But in NS,it will occur some issue since CAN0CTL1_CANE is write once register.

      

      How to slove it?

      Please give me some advice.Thanks a million.

0 Kudos
Reply
2,338 Views
kef
Specialist I

I don't think CANE set in bootloader is a big issue, at least I don't know how.

 

Solution is simple and I think you already know it: reset. Reset when switching from application to bootloader.  To switch back to application - reset after bootload session is done.

 

 

0 Kudos
Reply
2,338 Views
100asong
Contributor I

Hi,Dear Kef

 

     I has still difficulty about it. Perhaps my comprehend is wrong.So please give me hand.

    

     I think the CAN initialization code will been run again though reset. 

     Here is my detailed infromation:

    

     Afrer power on,bootloader runs firstly,it will initialize CAN,and it waits the command from HOST PC.

     If get nothing in 500ms,it will jump to application.And at this time,application will initalize CAN again.

     If get the program the flash command from HOST PC in 500ms,it will communicate with HOST PC and program the flash.When it finish,it will Reset.But after reset,MCU still run bootloader  initialization CAN code,and then jump to application,application will initialize the CAN again.Because bootloader CAN initialization code and application CAN initialization code are two different code,two alone code.

 

     If CAN init is only one code,it will been okay through reset.But based on my code,it is a little difficult for me to use only one initialization CAN code.

 

     Any advice is welcome.

 

0 Kudos
Reply
2,338 Views
kef
Specialist I

I think that you don't need to reset CANE bit, it can be kept set. To be able to reinitialize CAN module you only need to switch CAN mode back to initialization mode. That's possible without any MCU reset.

 

Anyway you can always reset whole MCU, even when going from bootloader to application, even if that should happen after running bootloader for 0.5s after power on.

 

0 Kudos
Reply
2,338 Views
100asong
Contributor I

Dear Kef,

     Thanks help me.

 

    In bootloader ,address belong to 0xF000-0xFFF,can initialization code is here:

    void bootloader_InitCAN0(void){
 
    CAN0CTL0 = 0x01;                // MSCAN in initialization mode
    while (!(CAN0CTL1_INITAK));    // Wait for initialization mode acknowledge
           
    CAN0CTL1_CANE = 1;              // Enable MSCAN module
  
 
    CAN0CTL1_LISTEN = 0;    // Not listen only mode       
    CAN0CTL1_WUPM = 1;
    CAN0CTL1_BORM = 1;

   ......

    
    CAN0IDAR0 = 0xFD;//(byte)(BOOT_RX_ID>>3);
    CAN0IDAR1 = 0x60;//(byte)((BOOT_RX_ID<<5)&0xE0);  // only down loader id is accepted
    CAN0IDAR2 = 0xFF;
    CAN0IDAR3 = 0xFF;

   
    CAN0IDMR4 = 0x00;   
    CAN0IDMR5 = 0x1F;   
    CAN0IDMR6 = 0xFF;   
    CAN0IDMR7 = 0xFF; 
   
    CAN0IDAR4 = 0xFD;//(byte)(BOOT_RX_ID>>3);
    CAN0IDAR5 = 0x60;//(byte)((BOOT_RX_ID<<5)&0xE0);  // only down loader id is accepted
    CAN0IDAR6 = 0xFF;
    CAN0IDAR7 = 0xFF;

 

    CAN0CTL0 = 0x00;          // Exit initialization mode request
    while (CAN0CTL1_INITAK);  // Wait for normal mode
                  
    CAN0CTL0 = 0x00;          // Exit initialization mode request                   
    CAN0RIER = 0x01;       // Enable Receive interrupt
   
    CAN0TIER = 0x00;          //disable send interrupt flag
    while(!(CAN0CTL0_SYNCH)); // Wait for CAN synchronization
  
    RxMsg.DtLen = 0; 
}

 

My application code CAN initialization is here,since it has some other feature and I can not use bootloader_InitCAN0 from bootloader.

void InitCAN(u8 channelNo,u8 baudrate)
{
  u32 _id;
 volatile MSCANReg *stCanMsgReg;
 volatile XGCANstruct *stXGCANStruct;
 
 //stXGCANStruct = (volatile XGCANstruct *)(&ChannelCAN0);
 
 #ifdef  USE_CAN0
 if(channelNo == 0)
 {
   stXGCANStruct = (volatile XGCANstruct *)(&ChannelCAN0);
 }
 #endif
 
 if(channelNo == 4)
 {
  stXGCANStruct = (volatile XGCANstruct *)(&ChannelCAN4); 
 }
 
 
 stCanMsgReg = (volatile MSCANReg *)stXGCANStruct->pCAN;  //get CAN register
 
 (stCanMsgReg->can_ctl0).Byte= 1;//MSCAN in initialization mode;
 while(stCanMsgReg->can_ctl1.Bits.INITAK != 1); //Initialization mode active
       
 
 (&stCanMsgReg->can_ctl1)->Bits.CANE = 1;// MSCAN module is enabled
 (&stCanMsgReg->can_ctl1)->Bits.LISTEN = 0;
 (&stCanMsgReg->can_ctl1)->Bits.WUPM = 1;
 #ifdef _PLL_
 //If we use OSC clk,set borm to 1;if we use BUS CLK,we should set CLK
 (&stCanMsgReg->can_ctl1)->Bits.CLKsrc=1;//assume the bus clk is 48M hz.

 (&stCanMsgReg->can_btr0)->Byte = 0xC0| baudrate;// SJW = 4, fcan=48M/4=12M
 (&stCanMsgReg->can_btr1)->Byte = 0x6f;// SAMP = 0, TSEG2 = 7, TSEG1 = 16, 24 Tq per bit, Baud=12M/24=500K
 #else
 (&stCanMsgReg->can_ctl1)->Bits.CLKsrc=0;//MSCAN clock source is the oscillator clock.
 (&stCanMsgReg->can_btr0)->Byte = 0x41;//250k
 (&stCanMsgReg->can_btr1)->Byte = 0x14;// SAMP = 0, TSEG2 = 2, TSEG1 = 5, 8 Tq per bit
 #endif
 //(&stCanMsgReg->can_ctl1)->Bits.BORM = 1; //Bus-off recovery upon user request
 (&stCanMsgReg->can_ctl1)->Bits.BORM = 0; //Bus-off automatic recovery
 (&stCanMsgReg->can_idac)->MergedBits.grpIDAM = 0b00;  //2*32bit

  (&stCanMsgReg->can_idmr0)->Byte = 0xff;// filter acceptance/mask
  (&stCanMsgReg->can_idmr1)->Byte = 0xff;// filter acceptance/mask
  (&stCanMsgReg->can_idmr2)->Byte = 0xff;// filter acceptance/mask
  (&stCanMsgReg->can_idmr3)->Byte = 0xff;// filter acceptance/mask
  (&stCanMsgReg->can_idmr4)->Byte = 0xff;// filter acceptance/mask
  (&stCanMsgReg->can_idmr5)->Byte = 0xff;// filter acceptance/mask
  (&stCanMsgReg->can_idmr6)->Byte = 0xff;// filter acceptance/mask
  (&stCanMsgReg->can_idmr7)->Byte = 0xff;// filter acceptance/mask 
 

 (&stCanMsgReg->can_ctl0)->Byte = 0x00;//clear INITRQ
 while((&stCanMsgReg->can_ctl1)->Bits.INITAK != 0);

 (&stCanMsgReg->can_ctl0)->Byte = 0x00;// clear INITRQ
 (&stCanMsgReg->can_rier)->Byte = 0x01;// receive interrupts
 (&stCanMsgReg->can_tier)->Byte = 0x00;// transmit interrupts

 while(stCanMsgReg->can_ctl0.Bits.SYNCH != 1); // wait for MSCAN to synchronize

 

 (u8*)(stXGCANStruct->tx_status) = 0x00;
 
 return;
}

 

They are 2 different code.

 

1.CANE is write once register.

   I can delete "(&stCanMsgReg->can_ctl1)->Bits.CANE = 1;// MSCAN module is enabled ",but "(&stCanMsgReg->can_ctl1)->Bits.LISTEN = 0" still operate register can_ctl1 and it affects also CANE bit,which means it write CANE second time.

   My comprehend is  right here?

2.Since "They are 2 different code.", I must initializate CAN moudle again in application.Here whether I have any other way?

 

 

 

0 Kudos
Reply
2,339 Views
kef
Specialist I

Write once bit doesn't mean you must do all your best limiting write accesses to write once bit. You may write to write once bit as many times as you wish, but only first write is accepted.

 

For exmple

1) default CANE bit state after reset is "0". 

2) First write to CAN0CTL1 with "1" in CANE bit position succeeds. "1" is locked to CANE bit. You may confirm that reading CAN0CTL1.

3) Second write to CAN0CTL1 with "0" in CANE bit position doesn't succeed, because this is second write to CAN0CTL1. Though you write "0" to CANE, you will read CANE==1.

 

Another example

1) default CANE bit state after reset is "0". 

2) First write to CAN0CTL1 with CANE=0 doesn't change state of CANE bit, but "0" is still locked to CANE.

3) You want to enable CAN module and write CANE=1 to CAN0CTL1, but wirte fails because CANE is already locked in CANE==0 state. You won't be able to enable CAN module in this case.

 

 

So to enable CAN you must only provide that first write to CAN0CTL1 is writing "1" to CANE bit. You need CAN enabled, so both, bootloader and application should not fail if CANE==1 before any of two canInit() routines.

 

To reconfigure CAN, you should switch from running mode to initialization mode by writing "1" to INITRQ bit. Both your CAN init routines are doing that.

 

 

0 Kudos
Reply
2,338 Views
100asong
Contributor I

I see till now,Thanks help.

0 Kudos
Reply