What Happens When Writing to a 'Readable Bit'? - Page 1
Forum section: electronics / general

author: SparkFly
author_rank: Regular Contributor
timestamp: September 07, 2021, 03:48:33 pm
content: I am new to programming microcontrollers, and have recently began a project where I would like to use the internal oscillator of a PIC16F819. Until now, I have been setting registers in the following way:OSCCON = 0b01110100However, the datasheet states that bit 2 of OSCCON is a only a readable bit - not writeable. What happens to this bit when I attempt to write to it, as in this case, with a '1'? What consequences might using this method have?I've tried investigating, but the closest I can find is from this page here:http://www.learningaboutelectronics.com/Articles/How-to-set-up-the-oscillator-for-a-PIC-microcontroller-in-C.php- where they say that writing a '1' "makes the signal stable". I think this is incorrect, as my interpretation of the datasheet is that this bit is only written to by the microcontroller, to indicate the stability of the oscillator.For convenience, here is the datasheet:https://ww1.microchip.com/downloads/en/DeviceDoc/39598F.pdfOSCCON register is described on page 38.

author: Ian.M
author_rank: Super Contributor
timestamp: September 07, 2021, 04:03:41 pm
content: If a bit is indicated as 'read only' in the data sheet, writes to it will not change its value. Consequences: None. However the consequence of writing code that *attempts* to write a specific value to a read-only bit is to confuse yourself and anyone who reads your code!

author: JPortici
author_rank: Super Contributor
timestamp: September 07, 2021, 04:04:17 pm
content: Quote from: SparkFly on September 07, 2021, 03:48:33 pmContrary to those people at learningaboutelectronicsyou understood it correctly. The bit can only be read (and in this case is set by the hardware to signal that the oscillator is stable)Writing to it has no effect.Note that according to microchip datasheets a bit in the hardware register can beR - Readable*W - WritableHS/HC/HSC - Set/Cleared/Set and cleared by hardwareC - Clearable onlyS - Settable onlyU - Undefined (discard the value, with a catch**)or a combination of the above, like R/HS/C-0 means that it's readable, can be set by hardware and you can only clear it. Its value at POR and other resets is 0*Ecxeption: the new UART peripheral has the buffer full/overflown bit that can be read and will indicate the status, if written to 0 there is no effect, if written to 1 clear the fifo and read back 0. so much fun when changing other bits of UxFIFO using RMW operations**Exception: There may be undefined/reserved bits in some peripheral and in configuration words that MUST be set to either zero or one at all times. You need not to know what they do (usually the debug flag, also other undocumented stuff) but follow what the datasheet says

author: SparkFly
author_rank: Regular Contributor
timestamp: September 07, 2021, 04:25:24 pm
content: Thanks both.What would be a better way of setting registers, to improve the readability of the code?

author: NorthGuy
author_rank: Super Contributor
timestamp: September 07, 2021, 04:39:38 pm
content: Quote from: SparkFly on September 07, 2021, 03:48:33 pmRegardless of the consequences (which are none for read-only bits), you cannot avoid writing the bit. Every time you write to a register, all 8 bits are written, even if you write with bcf/bsf instruction.

author: Ian.M
author_rank: Super Contributor
timestamp: September 07, 2021, 04:56:21 pm
content: You are loading a register with a 'magic' number. Nothing you can do can improve its readability, as one needs to refer to the datasheet anyway to understand it. Quoting an extract of the datasheet in a comment only helps if you get it right, and if there's a problem, can be a great waste of time if you made a typo!However if you wish to sacrifice readability for maintainability, you can use the SFR bitfield macros in the device specific header file.e.g. here's the macros for OSCCON from pic16F819.h for an older version of XC8 than ypu are probably using.Code:// bitfield macros#define _OSCCON_IOFS_POSN 0x2#define _OSCCON_IOFS_POSITION 0x2#define _OSCCON_IOFS_SIZE 0x1#define _OSCCON_IOFS_LENGTH 0x1#define _OSCCON_IOFS_MASK 0x4#define _OSCCON_IRCF_POSN 0x4#define _OSCCON_IRCF_POSITION 0x4#define _OSCCON_IRCF_SIZE 0x3#define _OSCCON_IRCF_LENGTH 0x3#define _OSCCON_IRCF_MASK 0x70#define _OSCCON_IRCF0_POSN 0x4#define _OSCCON_IRCF0_POSITION 0x4#define _OSCCON_IRCF0_SIZE 0x1#define _OSCCON_IRCF0_LENGTH 0x1#define _OSCCON_IRCF0_MASK 0x10#define _OSCCON_IRCF1_POSN 0x5#define _OSCCON_IRCF1_POSITION 0x5#define _OSCCON_IRCF1_SIZE 0x1#define _OSCCON_IRCF1_LENGTH 0x1#define _OSCCON_IRCF1_MASK 0x20#define _OSCCON_IRCF2_POSN 0x6#define _OSCCON_IRCF2_POSITION 0x6#define _OSCCON_IRCF2_SIZE 0x1#define _OSCCON_IRCF2_LENGTH 0x1#define _OSCCON_IRCF2_MASK 0x40Yours should be similar.The one of interest is _OSCCON_IRCF_POSN.Code:OSCCON=7<<_OSCCON_IRCF_POSN; // 7 for 8MHz (Fosc=125KHz*2^(N-1) or Frc if N=0. 7>=N>=0) DS39598E p38is about as good as it gets, though as there is only a single writable field in OSCCON and its nibble aligned and only implemented in a subset of 'classic' midrange PIC16F devices, I'd probably simply settle for:Code:OSCCON=0x70; // for 8MHz, see DS39598E p38

author: peter-h
author_rank: Super Contributor
timestamp: September 07, 2021, 06:42:23 pm
content: Whatever you do is fine if youcomment itcarefully, accurately, etc.There is a huge fashion among C programmers to comment nothing, "because C is obvious, and if somebody can't read it, they should not be coding". I come from an assembler background where almost every line would be commented (well, it was my own business so writing illegible code would be completely stupid) and I write C similarly.

author: Benta
author_rank: Super Contributor
timestamp: September 07, 2021, 07:02:11 pm
content: Quote from: NorthGuy on September 07, 2021, 04:39:38 pmIt can't be phrased better than this.

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 07, 2021, 08:05:02 pm
content: Quote from: SparkFly on September 07, 2021, 03:48:33 pmWhile the datasheet doesn't define what they call "readable" and "writable" (at least I haven't found that info), it's probably because it's one of those "obvious" concepts that almost everybody assumes. One may object that clearly defining this somewhere in the datasheet would not hurt...As others have said, when writing to registers, it's impossible to avoid "writing" to read-only bits, so you can safely assume that it has not effect. (But again, stating this somewhere in the datasheet wouldn't have hurt... that said, even if they had, chances are that most readers would have missed the info unless it was repeated along with each register definition... which would be cumbersome... so yeah... writing docs is hard.) While the written value for read-only bits doesn't matter, it makes sense to use '0' for those instead or '1', in order not to confuse people reading the code.And as others have also said, using constants for the various bits is much clearer, and the definitions are already there in the include files.Quote from: SparkFly on September 07, 2021, 03:48:33 pmYou got that right, that's bullshit. Lesson to learn is not to trust any random blog you find on the internet. They're full of crap, and the good ones are few.Note that the above in the blog you mentioned may have come from a bad interpretation of the datasheet (that you yourself didn't find completely clear), but the logic they used is pretty twisted. What kind of engineers would implement oscillators that would be "unstable" by default (whatever that means) and that would suddenly become stable when you set a given bit? That itself would be quite odd. Sure one could think of very particular oscillators that would default to a very low power, but unstable state (whatever that would mean though - that would then be surely clearly explained in the datasheet), and that you could switch to a "stable" state with a configuration bit, but drawing more power. You can rest assured that this is not the case here, that if it were, it would surely be explained (and promoted) in the datasheet. And again, anyway, this bit not being "writable", it should still be clear that writing to it would NEVER be *required*.

author: westfw
author_rank: Super Contributor
timestamp: September 08, 2021, 09:07:10 am
content: QuoteWell, except that a "register" with read-only bits probably doesn't actually have anything to actually WRITE in the read-only positions.We tend to think of registers as being "like" memory locations, but they don't need to be implemented that way - reads and writes can deal with completely separate signals on the chip. (consider a UART "data" register, where a write sends data to the transmit shift registers, but a read reads the receive shift register - a completely different part of the peripheral.)

author: MIS42N
author_rank: Frequent Contributor
timestamp: September 08, 2021, 09:59:04 am
content: Writes to read only bits do not alter them. This is the way I document writes to control registers. It's assembler but I think C accepts something similar. Tedious the first time but copy and paste is your friendCode:MOVLWB'10000000' ; enable DAC, source Vdd; 1 x 0 0 0 0 x x; | | | -+-; | | | +----- 00 = DAC Positive Source Vdd; | | +-------- 0 = DAC not connected to the DACOUT2 pin; | +---------- 0 = DAC not connected to the DACOUT1 pin; +-------------- 1 = DAC is enabledMOVWFDACCON0;; --- Comparator ---MOVLWB'00010010'; 0 0 0 1 x 0 1 0; | | -|- --+-- 010 = CxVN connects to CxIN2- pin; | | +--------- 01 = CxVP connects to DAC Voltage Reference; | +------------ 0 = No interrupt on a negative going edge; +-------------- 0 = No interrupt on a positive going edgeMOVWFCM1CON1MOVLWB'10000101'; 1 x 0 0 x 1 0 1; | | | | | + 1 = Comparator output to Timer1 is synchronous; | | | | +-- 0 = Comparator hysteresis disabled; | | | +---- 1 = Comparator operates in Normal-Power mode; | | +-------- 0 = Comparator output is not inverted; | +---------- 0 = CxOUT is internal only; +-------------- 1 = Comparator is enabledMOVWFCM1CON0;

author: Jan Audio
author_rank: Frequent Contributor
timestamp: September 08, 2021, 02:08:06 pm
content: The best way is like Ian shows you,the cool part is you dont have to write it yourself :Go to the menu and look for view, the select configuration bits or something ( sorry i,m not behind my PC now ).Now what you do is select all possibilities from a menu, and copy the whole code in your header file.Oops wrong subject, maybe you did not know either.

author: Bassman59
author_rank: Super Contributor
timestamp: September 08, 2021, 03:19:10 pm
content: Quote from: peter-h on September 07, 2021, 06:42:23 pmThe code showswhatyou're doing.Comments should explainwhyyou're doing it.

author: Bassman59
author_rank: Super Contributor
timestamp: September 08, 2021, 03:21:20 pm
content: Quote from: westfw on September 08, 2021, 09:07:10 amAll of that is true, but ... irrelevant!The OP asked about writing to read-only bits in a control register.The answer is: those bits don't get changed.Let's try to stay on target!

author: bson
author_rank: Unknown
timestamp: September 11, 2021, 08:11:21 pm
content: Writing a RO bit will do nothing at all to the value of that bit. The next time you read it it's unchanged.Writing a WO bit will enact some change. The next time you read it you get whatever the datasheet tells you it will read as: '0', '1', or undefined. The latter means you can't rely on it presenting some specific value, even if in practice you do get something specific.Sometimes CSR bits have to always be written with specific values, and aren't documented beyond that.