-
Notifications
You must be signed in to change notification settings - Fork 0
PIC18 UART Driver #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
AndrewWang001
wants to merge
8
commits into
main
Choose a base branch
from
uart-driver
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 6 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
8433b4d
add pic18 ltt uart driver
AndrewWang001 e8bc2ba
removed pps init, added bool controlled flow control and dynamic baud…
AndrewWang001 4a1aea6
added param checks and updated .h
AndrewWang001 5e99f23
fixed clang format
AndrewWang001 9012f55
fix syntax and format
AndrewWang001 3b2ab1a
fixed clang-format
AndrewWang001 f1d9a62
rough update based on pr review
AndrewWang001 f14431b
removed canlib dependancy etc
AndrewWang001 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| #ifndef ROCKETLIB_UART_H | ||
| #define ROCKETLIB_UART_H | ||
|
|
||
| #include <stdbool.h> | ||
| #include <stdint.h> | ||
|
|
||
| #include "common.h" | ||
|
|
||
| /* | ||
| * Initialize UART module. Set up rx and tx buffers, set up module, | ||
| * and enable the requisite interrupts | ||
| */ | ||
| w_status_t uart_init(uint32_t baud_rate, uint32_t fosc, bool enable_flow_control); | ||
|
|
||
| /* | ||
| * A lot like transmitting a single byte, except there are multiple bytes. tx does | ||
| * not need to be null terminated, that's why we have the len parameter | ||
| * | ||
| * tx: pointer to an array of bytes to send | ||
| * len: the number of bytes that should be sent from that array | ||
| */ | ||
| void uart_transmit_buffer(uint8_t *tx, uint8_t len); | ||
|
|
||
| /* | ||
| * returns true if there's a byte waiting to be read from the UART module | ||
| */ | ||
| bool uart_byte_available(void); | ||
|
|
||
| /* | ||
| * pops a byte from the receive buffer and returns it. Don't call this | ||
| * function unless uart_byte_available is returning true. Don't call this | ||
| * function from an interrupt context. | ||
| */ | ||
| uint8_t uart_read_byte(void); | ||
|
|
||
| /* | ||
| * handler for all UART1 module interrputs. That is, PIR3:U1IF, U1EIF, U1TXIF, and U1RXIF | ||
| * this function clears the bits in PIR3 that it handles. | ||
| */ | ||
| void uart_interrupt_handler(void); | ||
|
|
||
| #endif /* ROCKETLIB_UART_H */ | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| #include <pic18f26k83.h> | ||
| #include <stdbool.h> | ||
| #include <stdint.h> | ||
|
|
||
| #include "canlib.h" | ||
AndrewWang001 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| #include "canlib/util/safe_ring_buffer.h" | ||
| #include "common.h" | ||
| #include "uart.h" | ||
|
|
||
| // safe ring buffers for sending and receiving | ||
AndrewWang001 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| static srb_ctx_t rx_buffer; | ||
| static srb_ctx_t tx_buffer; | ||
|
|
||
| // memory pools to use for those srbs. 100 is a completely arbitrary number | ||
| uint8_t rx_buffer_pool[100], tx_buffer_pool[100]; | ||
|
|
||
| w_status_t uart_init(uint32_t baud_rate, uint32_t fosc, bool enable_flow_control) { | ||
| // only 12 or 48 MHz for pic | ||
| if (fosc != 12000000UL && fosc != 48000000UL) { | ||
| return W_INVALID_PARAM; | ||
| } | ||
|
|
||
| // bool controlled flow control. | ||
| U1CON2bits.FLO = enable_flow_control ? 0b10 : 0b00; | ||
|
|
||
| // low speed | ||
| U1CON0bits.BRGS = 0; | ||
| uint32_t divisor = (U1CON0bits.BRGS == 1) ? 4 : 16; | ||
|
|
||
| // checks if baud rate param within range | ||
| if (baud_rate == 0 || baud_rate > (fosc / divisor)) { | ||
| return W_INVALID_PARAM; | ||
| } | ||
|
|
||
| // don't autodetect baudrate | ||
| U1CON0bits.ABDEN = 0; | ||
| // normal mode (8 bit, no parity, no 9th bit) | ||
| U1CON0bits.MODE = 0; | ||
| // enable transmit | ||
| U1CON0bits.TXEN = 1; | ||
| // enable receive | ||
| U1CON0bits.RXEN = 1; | ||
|
|
||
| // keep running on overflow, never stop receiving | ||
| U1CON2bits.RUNOVF = 1; | ||
|
|
||
| // dynamic baud rate | ||
| uint16_t brg = (fosc / (divisor * baud_rate)) - 1; | ||
| U1BRGH = (brg >> 8) & 0xFF; | ||
| U1BRGL = brg & 0xFF; | ||
|
|
||
| // we are go for UART | ||
| U1CON1bits.ON = 1; | ||
|
|
||
| // initialize the rx and tx buffers | ||
AndrewWang001 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| srb_init(&rx_buffer, rx_buffer_pool, sizeof(rx_buffer_pool), sizeof(uint8_t)); | ||
| srb_init(&tx_buffer, tx_buffer_pool, sizeof(tx_buffer_pool), sizeof(uint8_t)); | ||
|
|
||
| // enable receive interrupt | ||
| IPR3bits.U1RXIP = 1; | ||
| PIE3bits.U1RXIE = 1; | ||
| // Do not enable transmit interrupt, that interrupt enable signals that | ||
| // there is data to be sent, which at init time is not true | ||
|
|
||
| return W_SUCCESS; | ||
| } | ||
|
|
||
| void uart_transmit_buffer(uint8_t *tx, uint8_t len) { | ||
AndrewWang001 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // just call uart_transmit_byte with each byte they want us to send | ||
| while (len--) { | ||
| srb_push(&tx_buffer, tx); | ||
| tx++; | ||
| } | ||
| // If the module isn't enabled, give it a byte to send and enable it | ||
| if (PIE3bits.U1TXIE == 0) { | ||
AndrewWang001 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| srb_pop(&tx_buffer, &tx); | ||
| U1TXB = tx; | ||
| U1CON0bits.TXEN = 1; | ||
| // also enable the interrupt for when it's ready to send more data | ||
| PIE3bits.U1TXIE = 1; | ||
| } | ||
| } | ||
|
|
||
| bool uart_byte_available(void) { | ||
AndrewWang001 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return !srb_is_empty(&rx_buffer); | ||
| } | ||
|
|
||
| uint8_t uart_read_byte(void) { | ||
AndrewWang001 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| uint8_t rcv; | ||
| srb_pop(&rx_buffer, &rcv); | ||
| return rcv; | ||
| } | ||
|
|
||
| void uart_interrupt_handler(void) { | ||
AndrewWang001 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (PIR3bits.U1TXIF) { | ||
| // check if there are any bytes we still want to transmit | ||
| if (!srb_is_empty(&tx_buffer)) { | ||
| // if so, transmit them | ||
| uint8_t tx; | ||
| srb_pop(&tx_buffer, &tx); | ||
| U1TXB = tx; | ||
| } else { | ||
| // If we have no data to send, disable this interrupt | ||
| PIE3bits.U1TXIE = 0; | ||
| // if not, disable the TX part of the uart module so that TXIF | ||
| // isn't triggered again and so that we reenable the module on | ||
| // the next call to uart_transmit_byte | ||
| U1CON0bits.TXEN = 0; | ||
| } | ||
| PIR3bits.U1TXIF = 0; | ||
| } else if (PIR3bits.U1RXIF) { | ||
| // we received a byte, need to push into RX buffer and return | ||
| uint8_t rcv = U1RXB; | ||
| srb_push(&rx_buffer, &rcv); | ||
| PIR3bits.U1RXIF = 0; | ||
| } else if (PIR3bits.U1EIF) { | ||
| // Some sort of error, ignore for now (TODO?) | ||
| PIR3bits.U1EIF = 0; | ||
| } else if (PIR3bits.U1IF) { | ||
| PIR3bits.U1IF = 0; | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.