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?
Solved! Go to Solution.
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.
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.
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.
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.
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.
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.
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?
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.
I see till now,Thanks help.