Content originally posted in LPCWare by rw_ on Fri Jan 04 17:36:23 MST 2013
Quote: Helmut Stettmaier
Hello,
at first let me whish a "Happy New Year" to all of you.
Happy New Year to you too!
Quote: Helmut Stettmaier
I want to start a becoming-familiar-project for the LPC800 (my first ARM:-) using the UART. Of course I want to use the driver in the device's ROM, but this turns out to be a bit complicated.
I'm glad to hear that you're using the LPC8xx as your first ARM part. I hope that you'll like it as much as I do!
Quote: Helmut Stettmaier
Can anybody please tell me where I can find more detailed descriptions or even tutorials of the ROM drivers extending and completing the notes in the "LPC800 User manual", Rev. 1.0 (UM10601)? (Ok, I understand, this is a draft, but perhaps you are interested in one more proof reader?)
Interestingly, I'm currently working on the same code. A ROM-API based driver for the UART. Perhaps we can share some information about it here?
Quote: Helmut Stettmaier
As the UART driver is most likely used by ISP I think that it is tested and that it works. Checking and reading what I could find yielded some questions.
I was able to get the ROM-API UART working. Hopefully, this effort will help answer some of your questions. I don't yet know what I don't know about it :)
Quote: Helmut Stettmaier
1. Is uart_get_char() really blocking? Is uart_get_line also blocking (nothing said explicitely in chapter 24.4.6, only the existence of the error message "ERR_UART_RECEIVE_ON - UART receive is ongoing" lets me take some hope that it doesn't block).
As far as I understand it, #1 yes, uart_get_char is really "blocking." It is a "polled only" mode function that, once setup/configured/initialized, works very much the same as a non-ROM based driver, but without having to manually check the RXRDY/RXIDLE bits yourself. Additionally, if a byte in not received, it will block indefinitely waiting for a byte once called. I have tested this in my own code where I call it with a breakpoint on the call and another breakpoint after the call. It will not reach the later BP until after I "send" a character from my terminal program to the LPC8xx. This is also the case when calling get_line in "polling" mode. Interrupt mode is the key to not blocking.
Quote: Helmut Stettmaier
2. How can I "watch" the serial line until a block of bytes has been received?
"Blocks" in this context are byte sequences separated by pauses (HI level) of at least one byte duration, so a block is catched by awaiting & reading a stream, an IDLE-event and then counting the length of the received data. Blocks can be longer than the ones I'm interested in, so more than n bytes need not to be buffered, I just await the pause in such cases.
I don't know if I have a "real" answer for you with regard to the specific elements posed by your question and objective(s). I can offer what I *think* about it based on what I've learned so far, but I don't yet know if it is true or not for sure without further testing and coding to see if what I think is how it works.
Basically, you will want to implement your callbacks per the following signature:
typedef void (*UART_CALLBK_T)(uint32_t err_code, uint32_t n);
In my examples/tests, I simply created one for each of receive data and transmit data. While perhaps not very original, I arbitrarily used rx_callback and tx_callback. I haven't yet figured out a way to use a single callback for both RX and TX needs, but perhaps I will? :)
During your configuration of the put_line or get_line, the parameter argument needs to have the callback specified and the "transfer or receive mode" (transfer_mode member of the UART_PARAM_T structure and, of course, the "driver_mode" member needs to be 0x01 for "interrupt mode."
Additionally, you will want to enable the UARTn_IRQ in the NVIC before passing the parameter in on the put/get_line ROM calls, else no interrupt will fire. In your ISR for the UART, you will want to call the uart_isr passing the respective handle for the given UART that you received back from the API when you called uart_setup. That will then invoke the callback respective for the rx or tx that you passed in your "param" argument to the get/put_line function.
In order to "watch" it, you may have to configure your buffer for over/under run sizing such that you can force the eventuality that you expect/desire and then process the condition in the callback with the error_en bit(s) set per your needs.
Quote: Helmut Stettmaier
I have already programmed this for another processor, this question however concentrates on how to do this using the ROM drivers.
I *may* be able to help you through your specific effort, but if not, perhaps some of my reply may help you understand it better? Please let me know if you need any clarification of my points.
Quote: Helmut Stettmaier
3. Does uart_get_mem_size return a fixed number? May I use a fixed, statically allocated block as long I am sure of the driver version? I do NOT want to use malloc() or something similar.
My experiences indicate that, for at least the part I'm working with and the ROM driver version in the chip, the size returned by get_mem_size is fixed at 0x20 bytes. I'm not exactly sure whether there is any value to ever calling it unless it is to see if perhaps the size changed in some future release and whether or not your code will break as a result.
Quote: Helmut Stettmaier
4. If I cannot use the driver or, more likely, if I must extend it by application code: I could not find a definition when the RX enters idle mode: Immediately after scanning the stop bit or after some additional time. Or must I use a timer to detect the pause after a block?
I think that you'll want to configure for interrupt driven mode using the buffer size that meets your needs for the kind of transfers you're expecting and then enable to various error bits in the UART_CONFIG_T structure (error_en member) so that you will receive a callback from the corresponding interrupt sources/INTENSET such as OVERRUNEN, DELTARXBRKEN or "under run" (when receiving less than a full "buffer") and that by doing these configurations and handling the various states using status bits in your callback, you should be able to achieve your objectives. Note that I prefaced all of this with "I think" :) I am still experimenting with some of the finer-grained uses of the ROM API.
My first thought is that when the RX enters the idle state, assuming no error state, that the callback would be fired
Quote: Helmut Stettmaier
Hmmm, a bit of a chunk for my first question... Thank you for your attention and your time!
Helmut
Yes, it is a bit of a chunk for your first few questions :D ...but after working through it and getting it working for my needs, I can appreciate the effort.
rw_