The program is to receive a byte from the host PC via UART0 on KL25Z. The data is fetched from Data Register D and assigned to a variable, c. Then controlled by the value of each bit of c, tri-color LEDs are lightened. The program works well with no problem.
When Keil enters ‘debug session’, I set a breakpoint to observe c and UART0->D.
[code][1]
[watch c][2]
After sending a byte from a terminal emulator software on PC, the program stops at the breaking point as RDRF (Receive Data Register Full) flags. At this moment, it can be observed data in Data Register is 0x61 which is the ascii code of letter ‘a’ and there is no value in variable, c.
[UART0_D][3]
[watch c][4]
If stepping by one line, variable c is supposed to be equal to 0x61. However, the result is c is 0 and Data Register is emptied. Because c is 0, LEDs are not lightened accordingly. I don’t understand why?
[UART0_D][5]
[watch c][6]
The setting for debug is as follows.
[debugger selection][7]
[debugger settings][8]
I'm running short of 10 reputation points to post more than 2 links. Relative images are attached here. Sorry for the inconvenience.
image link
Thanks.
Related
I'm using arm-none-eabi-gcc 5.3 to produce binaries for STM32L4. I'm using bootloader to flash program. Problem is I can't be sure if I'm flashing whole file. I don't have any CRC available. Flash starts on 0x80000000 and 0x80040000 (2 banks for bootloader and main program). Currently I assuming If 0x80040004 is between 0x80040000 and 0x80080000, program is flashed. But how can I check if program is valid? I can't find where is size of binary that should be written on flash, so I can check last few integers.
Here is first few bytes from BIN (sorry, can't post whole file):
Last byte that is not programmed is 0x80051C00 (program has 72704 bytes).
The most likely error is loss of data connection during the transfer so that the image is only partially written. The chances of programming error once the data is received is probably negligible, although your transfer protocol should include some sort of data integrity check. For that you could simply validate the checksum of hex-file records or use a protocol with CRC error checking such as XMODEM-CRC or XMODEM-1K.
Ensuring that you do not attempt to start a partially loaded application image is simple. It is not necessary to program the flash in address order or even the order the data arrives in. Given that, when the data for the reset-vector at 0x80040004 is received, you retain it in RAM and program it last. That way the reset vector value will always be 0xFFFFFFFF if the programming did not complete:
Pseudo-code:
WHILE receiving data
IF program_address in range
// Write all data except address at reset vector
IF program_address == 0x80040004
start_address = program_data
ELSE
write( program_address, program_data )
ENDIF
ENDIF
ENDWHILE
// Write reset vector *LAST*
write( 0x80040004, start_address )
Then in the start-up code:
IF #0x80040004 == 0xFFFFFFFFFF
NO APPLICATION - DO SOMETHING!
ELSE
START APPLICATION
ENDIF
I am using the 8051 microcontroller to read, write, and erase from flash memory.
Attached are the waveform for programming operations
And below is the code that I have written in order to recreate the waveform in order to write data into the chip:
void quick_write_op(void)
{
unsigned char i;
char SFRPAGE_SAVE=SFRPAGE;
SFRPAGE=CONFIG_PAGE;
//test=1;
Vpp_en=0; //8 volts is supplied to the board. Read/Write operations allowed
//Wait at least 1us between Vpp high and CSn low
for(i=0;i<2;i++){}
//Set-Up program command
P5=0x40;CSn=0;WEn=0;WEn=1;CSn=1;
//Program Command (Latch Address & Data)
P5=data_byte;CSn=0;WEn=0;WEn=1;CSn=1;
//Wait at least 10us for programming
for(i=0;i<23;i++){}
//Program Verify Command
P5=0xC0;CSn=0;WEn=0;WEn=1;CSn=1;
//Wait at least 6us for program verify
for(i=0;i<17;i++){}
//Program Verification
P5MDOUT=0x00; //Configured pins to open-drain
CSn=0;OEn=0;
OEn=1;CSn=1;
//Resets the command register
P5MDOUT=0xFF;
P5=0x00;CSn=0;WEn=0;WEn=1;CSn=1;
Vpp_en=1; //8 volts is now removed
//test=0;
SFRPAGE=SFRPAGE_SAVE;
}
I am going to assume that this code is fairly simple to follow seeing that there is a picture to go along with it detailing what I should do. If for some reason that it is hard to follow, then please let me know and I will clarify by adding code, images, etc.
I don't believe that there is a timing issue anywhere as I have checked that with a logic analyzer. When I invoke the write command, I want to write a 0x55 to address 0x00000, I should expect to see a 0x55 at address 0x00000. Instead, I am reading back an empty address, 0xFF. Therefore being forever stuck in the WRITE_LOOP until the right data is read in. Of course I may be blinded by my own bias so if I could get extra pairs of eyes on this and advice then I would greatly appreciate it. Thank you all.
I'm writing a bootloader for a c166 chip, to be exact, the 169FH. The bootloader can currently open a TCP/IP Connection so a PC can send an Intel hex file to the bootloader. This intel hex file is saved in the RAM. After receiving the hex file it is read line by line to set the bytes to the correct location in the flash. The flash location where the bootloader is stored is ofcourse different from where the main program can be saved.
This are the first two lines of the intel hex file:
:0200000400C03A
:20100000CA11EE111212341258127A129A12BC12DE12001322134413601388138813881349
The first line is to get the highest 16 bits of the 32bit flash address, which is in this case 0x00C0
in the second line are the lower 16 bits of the 32 bit flash address, which is in this case 0x1000. This creates to total address of 0x00C01000, the byte written to that address should be 0xCA.
I'm trying to write the byte to that address using the following code:
uint8_t u8Byte = (uint8_t )XHugeStringToDec((const __huge char *)&Ext_RamFlashSave.Byte[u32Idx], 9+(u8ByteIdx*2), 2);
uint8_t *u8Address = (uint8_t*)((uint32_t)(u32ExtendedLinearAddress << 16) + (uint32_t)u16BaseAddress + (uint32_t)u8ByteIdx);
*u8Address = (u8Byte);
XHugeStringToDec() is a function to get the hexadecimal value from the intel hex string. I know this is going correct.
Ext_RamFlashSave.Byte is the array where the intel hex file is storedin.
The u32ExtendedLinearAddress variable is 0x0C00, and is set earlier. The u16BaseAddress is 0x1000 and is also set earlier in code.
The problem is in the last line:
*u8Address = (u8Byte);
I have verified that u8Address is indeed 0x0C01000 and u8Byte is indeed 0xCA. But when I monitor my flash address, I do not see the byte written.
I can imagine that it is some kind of write protection, but I cannot find out how to work around this, or do I need a different way to write to the Flash address?
More info of how the intel-hex file is build is described here:
https://en.wikipedia.org/wiki/Intel_HEX
I am not familier with the chip you said.
But for writing to flash, Generally, following algorithm is used:
Unlock the flash. This is usually sending specific data sequence. The flash I use right now has 0xA0A0-> delay of 1msec -> 0x0505. This will enable writing to flash
Clear the error flags. Flash has some error flags like Write error or read error. Also, check for Busy flag to make sure Flash is ready
Erase the Page. Yes... You have to erase the page before writing to it. Even if you want to change a single bit, You have to erase entire page.
Write the data (Finally) But make sure that endien-ness is correct. Sometimes you Controller is Little Endien and Flash is Big Endien. So you have to match to Flash's.
Lock the Flash. This is usually done by sending same sequence which used for unlocking. (Refer Datasheet)
You cannot write to a flash directly... Have to go through entire process. That's why Flash are slow.
Some flash support 8bit writing while some only 16bit or 32 bit etc. So, you have to send those many bits while writing.
When you have to modify a small portion of a page, Read the page in a buffer. Modify data in the buffer. Erase the page and write entire buffer.
If you are modifying a
In xv6 MIT operating system, I'm trying to understand what is the different between the a few putc functions in /xv6/console.c
static void cgaputc(int c).
void uartputc (int c).
static void constputc(int c).
Thanks!
consputc() is a console output function. It writes a char to the console, which in that OS appears to mean both the serial port and the CGA text display. Before doing that, it first checks if the system has panicked (a panic is the state which the kernel enters when it has encountered an error and doesn't know what to do, so instead of going ahead and probably making matters worse decides to panic and stop), and if so, enters an infinite loop with interrupts disabled, so only a system reset can leave the panic state.
uartputc() writes a char to the serial port. It first checks that the serial port is not busy, and will accept the char.
cgaputc() writes a char to the CGA text framebuffer, and adjust the cursor position accordingly. The CGA text framebuffer starts at address 0xb8000, and consists of interleaved (attribute, character) bytes. The default mode, mode 3 is a 80x25 (80 columns, 25 rows) text mode. Attribute 07 means gray text on black background. The cursor position is manipulated via the CRT controller port, which exposes several registers, registers 14 and 15 hold the cursor position as 14 bits. The CRTC is accessed by first selecting a register to access by writing its number to the index CRTC port at 0x3d4, and then writing or reading from the CRTC control/data port at 0x3d5. This stuff is documented in a document called vgadoc4b, and in Ralph Brown's interrupt list.
You can see what all these functions do if you consult the code.
consputc(int c) clears interrupts then calls uartputc() and then calls cgaputc().
uartputc(int c) uses in and out to write c to the serial port (UART)
cgaputc(c) appears to be a console input/output function. Writes c to the serial port or the console, and it also sets the position of the cursor and sets the color for the console (black on white)
That's what I get from reading the code anyway, I have not used these functions before, but it seems pretty straight forward.
Upon reset of the 8051 microcontroller, all the port-pin latches are set to values of ‘1’. Now I am reading this book "Embedded C" and it states thr problem with the below code is that it can lull the developer into a false sense of security:
// Assume nothing written to port since reset
// – DANGEROUS!!!
Port_data = P1;
If, at a later date, someone modifies the program to include a routine for writing to all or part of the same port, this code will not generally work as required:
unsigned char Port_data;
P1 = 0x00;
. . .
// Assumes nothing written to port since reset
// – WON’T WORK BECAUSE SOMETHING WAS WRITTEN TO PORT ON RESET
Port_data = P1;
Anyone with knowledge of embedded c can explain to me why this code won't work? All it does is assign 0 to a char variable.
Potential issues.
1) The data direction register (DDR) associated with the port may not be set as expected, thus on power-up, the DDR may be set to "input". So writing the port to 0 may unexpectedly not read read 0.
2) The data direction register associated with the port may have been set to "output" and "reading" the data may not have a clear meaning. Depending on architecture, phantom bits may be needed to shadow the output bits for read-back.
3) Power-up code may get entered via a reset command that is nothing more than a jump to "reset vector". So any hardware specific action associated with a "cold" power-up did not occur as this is a "warm" power-up.
Solution:
On power-up code, explicitly set the DDR and output values (and shadow bits as needed).
May not apply to 8051 - speaking to embedded processor in general.
I was reading the same book and having the same confusion few months ago. Latter working on projects with PIC18 and M0+ and being kind of figuring out what it's really about.
Actually, this is not a software/programming issue but rather a hardware/electronic one. If your 805X code want to be able to read both 1 and 0 from an outside input on a pin, the code has to write 1 to the pin in advance. If your code write 0 to the pin in advance, the outside peripheral won't be able to pull the pin high and allow the code to read 1. Why?? electronic stuff!! Imagining that if you want to enjoy the wind outside the window, you have to open the window first.
If you are really interested, google "pin value vs latch value" by yourself. I think it's okay for programmer to leave that to hardware engineer.I believe 805Xs don't have DDR as advanced ones. Switching a pin between input and output mode may be easy but confusing.