Msp430 i²c module and libraries - i2c

I have a project that has a MSP430G2553 master device and a Triple-Axis Digital-Output Gyro ITG-3200 Breakout slave. ITG3200 uses i²c protocol to communicate so i've been checking out the i²c module usage on Msp. For a starter i downloaded the TI I²c examples which can be found in http://www.ti.com/lsds/ti/microcontroller/16-bit_msp430/msp430_software_landing.page After i debugged the first code which is between a MSP master and a TMP100 temperature sensor as a slave. Here is the sample code.
//******************************************************************************
// MSP430G2xx3 Demo - USCI_B0 I2C Master to TMP100, Set P1.0 if Temp > 28C
//
// Description: I2C interface to TMP100 temperature sensor in 9-bit mode.
// Timer_A CCR0 interrupt is used to wake up and read the two bytes of
// the TMP100 temperature register every 62ms. If the temperature is greater
// than 28C, P1.0 is set, else reset. CPU is operated in LPM0. I2C speed
// is ~100kHz.
// ACLK = n/a, MCLK = SMCLK = TACLK = BRCLK = default DCO = ~1.2MHz
//
// /|\ /|\ /|\
// | TMP100 10k 10k MSP430G2xx3
// | ------- | | -------------------
// +--|Vcc SDA|<-|---+->|P1.7/UCB0SDA XIN|-
// | | | | | |
// +--|A1,A0 | | | XOUT|-
// | | | | |
// +--|Vss SCL|<-+------|P1.6/UCB0SCL P1.0|---> LED
// \|/ ------- | |
//
// D. Dang
// Texas Instruments Inc.
// February 2011
// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
//******************************************************************************
#include <msp430.h>
unsigned int RxByteCtr;
unsigned int RxWord;
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= BIT0; // P1.0 output
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = 0x4e; // Set slave address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
IE2 |= UCB0RXIE; // Enable RX interrupt
TACTL = TASSEL_2 + MC_2; // SMCLK, contmode
while (1)
{
RxByteCtr = 2; // Load RX byte counter
UCB0CTL1 |= UCTXSTT; // I2C start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0, enable interrupts
// Remain in LPM0 until all data
// is RX'd
if (RxWord < 0x1d00) // >28C?
P1OUT &= ~0x01; // No, P1.0 = 0
else
P1OUT |= 0x01; // Yes, P1.0 = 1
__disable_interrupt();
TACCTL0 |= CCIE; // TACCR0 interrupt enabled
__bis_SR_register(CPUOFF + GIE); // Enter LPM0, enable interrupts
// Remain in LPM0 until TACCR0
// interrupt occurs
TACCTL0 &= ~CCIE; // TACCR0 interrupt disabled
}
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TA0_ISR(void)
{
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
// The USCIAB0TX_ISR is structured such that it can be used to receive any
// 2+ number of bytes by pre-loading RxByteCtr with the byte count.
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
RxByteCtr--; // Decrement RX byte counter
if (RxByteCtr)
{
RxWord = (unsigned int)UCB0RXBUF << 8; // Get received byte
if (RxByteCtr == 1) // Only one byte left?
UCB0CTL1 |= UCTXSTP; // Generate I2C stop condition
}
else
{
RxWord |= UCB0RXBUF; // Get final received byte,
// Combine MSB and LSB
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
I built up the same circuit where 2 10k pull ups on SDA and SCL, changed the slave address to either 0x69 or 0x68 which is the gyro address given in the user guide of the device. Since i did not built up any monitoring yet, i used an oscilloscope to check out the pulses on SCL and SDA. I didn't expect to see anything on SDA yet but what i am wondering is why i can't even see any clock cycle on SCL bus. It is either always on 3.3V (MSP internal vcc) or sometimes, its near 1V (0.80~). Even when i remove the gyroscope, SDA and SCL bus, i can't see any pulses on P1.6 port. Any ideas?

Related

How can I toggle two LEDs at difference frequencies using SYSTICK on keil for the ST32 processor

I want to toggle each LED one aT 4Hz and one at 3Hz, so far i can only toggle 2 at the same frequency.So far i can do them separately only but i dont know how to write to code to combine them so i can run it all at the same time.
// THIS CODE IS FOR BOTH
int main (void){
//Enable clock for GPIO A and Gpio B
RCC->AHB2ENR |= 0x3UL;
//Configure PA_0 and PA_1
GPIOA->MODER &= ~0xFUL ;
GPIOA->MODER |= 0x5UL;
GPIOA-> PUPDR &= ~0XFUL;
GPIOA-> PUPDR |= 0xAUL;
//FOR LED GREEN
SysTick ->LOAD = 1000000-1 ;
SysTick-> VAL = 0;
SysTick->CTRL |= 0x5UL;
while (1)
{
if (SysTick -> CTRL & SysTick_CTRL_COUNTFLAG_Msk)
{
GPIOA->ODR ^= 0x2UL;
}
}
}
//THEN deleting LED GREEN TO WRITE LED orange
SysTick ->LOAD = 666667-1 ;
SysTick-> VAL = 0;
SysTick->CTRL |= 0x5UL;
while (1)
{
if (SysTick -> CTRL & SysTick_CTRL_COUNTFLAG_Msk)
{
GPIOA->ODR ^= 0x1UL;
}
}
}
i just need help to combine them mainly the systick->load for each led.
Do not use systick this way. Set the systick interrupt to be triggered lets say 1000 times per second (standard STM startup files do it this way)
Then toggle LEDs in the interrupt handler
volatile uint32_t count = 0;
void SysTick_Handler(void)
{
count++;
if(!(count % (1000 / 8))) GPIOA -> ODR ^= 1; // 4 blinks per secons
if(!(count % (1000 / 6))) GPIOA -> ODR ^= 2; // 3 blinks per second
}

STM32 ADC initialization without HAL

I'm trying to write some basic code without HAL to initialize and read from an ADC, but I can't get it respond properly. I'm using an STM32F103C8T6 on a blue pill dev board. Function is the following:
Pin B1 (ADC9) is connected to a 0-3.3V signal (a 12V supply voltage through a voltage divider)
When the signal goes below a constant that i've called SUPP_V_MIN_VAL, pin B9 is set. If the signal is above that value, pin B9 is cleared.
I defined SUPP_V_MIN_VAL to be 2606.0. I am casting everything as a float because, in a separate section in my code, i need to display the current ADC value as a float).
The issue is that I think I am not initializing my ADC properly, or not casting my types properly. I'm finding that the ADC reading is always 0. My initialization is below:
RCC->APB2ENR |= 0x1UL << 3; //Initialize clock for GPIOB (bit 3), if it hasn't been initialized yet
RCC->APB2ENR |= 0x1UL << 9; //Initialize clock for ADC1 (bit 9), if it hasn't been initialized yet
GPIOB->CRL &= ~(0xF0UL); //SetBar pin PB1 to analog input
//ADC1->CR1 |= 0x0UL; //Default settings are correct - ignore
ADC1->CR2 |= 0x2UL; //Enable ADC1_CR2_CONT for continuous conversion
//ADC1->SMPR1; //ADC channels in SMPR1 are not used - ignore
ADC1->SMPR2 |= 0x38000000UL; // Set SMP9 to 239.5 cycles (set bits 27-29 to 1)
ADC1->CR2 |= 0x1UL; //Set CR2_ADON to wake up ADC from sleep mode
ADC1->CR2 |= 0x1UL << 3; //Initialize calibration register
while ((ADC1->CR2 >> 3) & 0x1UL); //Wait until calibration register is initialized
ADC1->CR2 |= 0x1UL << 2; //Enable calibration
while ((ADC1->CR2 >> 2) & 0x1UL); //Wait until calibration completed
ADC1->CR2 |= 0x1UL; //Set CR2_ADON again to turn on ADC and start converting
I am reading the pin with:
void pollSUPP(void)
{
uint16_t ADC_Reading = ADC1->DR;
suppVolt.float_var = (float) ADC_Reading;
if( suppVolt.float_var < SUPP_V_MIN_VAL)
{
// digitalWrite(SUPP_LOW, HIGH); PB9
GPIOB->BSRR = 0X1 << 9;
}
else {
GPIOB->BRR = 0X1 << 9;
}
}
SuppVolt is defined as
union {
float float_var;
uint8_t chars[4];
} suppVolt; //ADC reading for supply voltage
I may also be doing something stupid (I haven't actually confirmed that Pin B9 is on ADC1, but I am assuming it is since the blue pill only has one ADC??) or referencing the wrong bit in a register.
Can anyone help me spot my error? Thank you in advance!!

STM32F103C8T6 can not communicate with HD44780

I'm trying to control a HD44780 16X2 LCD(4 bit
communication) using a STM32F103C8T6.
I connected the LCD this way:
RS => PA0
EN => PA2
RW Ground
D7 => PB7
D6 => PB6
D5 => PB5
D4 => PB4
The LCD doesn't display anything. Where might the problem be? Does anyone know something about this issue?
Here is my code:
#include "delay.h"
#include "stm32f10x.h" // Device header
void lcd_command(unsigned char command);
void lcd_init(void);
void lcdPosition(unsigned int row, unsigned int column);
void lcd_data(unsigned char data);
int main() {
delay_init();
RCC->APB2ENR |= 1 << 2; // Port A Enabled.
RCC->APB2ENR |= 1 << 3; // Port B Enabled.
GPIOA->CRL = 0x22222222; // A0 and A2 Output.
GPIOB->CRL = 0x22222222; // B7,B6,B5,B4 Output.
GPIOB->ODR = 0x00; // Port B clear.
delay_ms(20);
lcd_command(0x30); // Datasheet says.
delay_ms(5);
lcd_command(0x30); // Datasheet says.
delay_ms(1);
lcd_command(0x30); // Datasheet says.
delay_ms(1);
lcd_init();
lcdPosition(1, 1); // first row first column
delay_ms(1);
lcd_data('A'); // Letter A
while (1)
;
}
void lcd_command(unsigned char command) {
GPIOA->BRR |= 1 << 0; // RS reset.
GPIOA->BSRR |= 1 << 2; // E set.
GPIOB->ODR = command; // upper nibble
delay_ms(2); // delay
GPIOA->BRR |= 1 << 2; // E reset.
GPIOB->BRR = 0x000000F0; // clear data bits
delay_ms(2); // delay
command = command << 4; // lower nibble
GPIOA->BSRR |= 1 << 2; // E set.
GPIOB->ODR = command; // lower nibble
delay_ms(2); // delay
GPIOA->BRR |= 1 << 2; // E reset.
GPIOB->BRR = 0x000000FF; // clear data bits
}
void lcd_init() {
lcd_command(0x02); // Return
delay_ms(2); // delay
lcd_command(0x28);
set 4 - bit data, 2 - line, 5x7 font delay_ms(2); // delay
lcd_command(0x0C);
turn on display, cursor off.delay_ms(2); // delay
lcd_command(0x01); // Clear.
delay_ms(2); // delay
lcd_command(0x06);
move cursor right delay_ms(4); // delay
}
void lcdPosition(unsigned int row, unsigned int column) {
if (row == 1) {
column--;
lcd_command(0x80 + column); // Define row
} else if (row == 2) {
column--;
lcd_command(0xC0 + column); // Define column
}
}
void lcd_data(unsigned char data) {
GPIOA->BSRR |= 1 << 0; // RS reset.
GPIOA->BSRR |= 1 << 2; // E set.
GPIOB->ODR = data;
upper nibble first delay_ms(4); // delay
GPIOA->BRR |= 1 << 2; // E reset.
GPIOB->BRR = 0x000000F0; // clear data bits
delay_ms(4); // delay
data = data << 4; // lower nibble
GPIOA->BSRR |= 1 << 2; // E set.
GPIOB->ODR = data; // lower nibble
delay_ms(4); // delay
GPIOA->BRR |= 1 << 2; // E reset.
GPIOB->BRR = 0x000000FF; // clear data bits
}
Also PA0 and PA2 are not 5V tolerant pins, usually HD44780 is 5V device, if it runs on +5V refer to the datasheet in Table 5. "Medium-density STM32F103xx pin definitions", if the pin is 5V tolerant in column I/O level it should be denoted with FT!
Please read carefully how to initialize 4-bit interface in the datasheet at page 46, figure 24.
In short: your lcd_command sends two nibbles one after another, but you are required to send only one nibble for first several commands (since the display controller still is in the 8-bit mode). You'll need to have a separate function to send only one nibble.

STM32F7: ADC DMA transfer only works once

I want to continuously read ADC values and write them into an array using the DMA. The board I am using is a Nucleo board with the STM32F767ZI.
To keep stuff like outputting data simple I am using the Arduino IDE with the STM32 board package.
I was able to get the ADC to work in continuous mode, but when I add the DMA it will not work. Only one single value seems to be transferred. The NDTR-register containing the amount of data to be transferred stays at the value I set it to minus one.
Here is the little program:
volatile static bool dma_active = 1;
#define maxSamples 512
int16_t dataPoints[maxSamples];
void setup() {
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // GPIOA clock enable
GPIOA->MODER |= (0b11 << 6); // PA3 as analog input
Serial.begin(115200);
Serial.println("starting");
initADC();
initDMA();
}
void initADC() {
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // ADC1 clock enable
ADC1->CR2 |= ADC_CR2_ADON; // ADC on
ADC1->CR2 |= ADC_CR2_CONT; // continuous conversion mode
ADC1->CR1 |= ADC_CR1_EOCIE; // EOC interrupt
ADC1->CR1 &= ~ADC_CR1_DISCEN; // discontinuous mode disabled
ADC1->CR1 &= ~ADC_CR1_SCAN; // scan mode disabled
ADC1->CR2 |= ADC_CR2_DMA; // DMA mode
ADC1->CR2 |= ADC_CR2_DDS; // continuous DMA request
ADC1->SQR3 |= 0b11; // ADC1_IN3 = PA3
ADC1->SQR1 &= ~(0b1111 << ADC_SQR1_L); // 1 conversion
ADC1->CR2 |= ADC_CR2_SWSTART; // Start conversion
}
void initDMA() {
// DMA2 Stream4 : Channel 0 is ADC1
RCC->AHB1ENR |= (1 << 22); // DMA2 clock enable
DMA2_Stream4->CR &= ~DMA_SxCR_EN; // Disable
while (DMA2_Stream4->CR & (1 << 0));
DMA2_Stream4->CR |= (0b0100 << DMA_SxCR_CHSEL); // Channel 4
DMA2_Stream4->CR |= (0b11 << DMA_SxCR_PL); // Very high priority
DMA2_Stream4->PAR = (uint32_t)&ADC1->DR; // Data source register
DMA2_Stream4->M0AR = uint32_t(&dataPoints); // Buffer 1
// DMA2_Stream4->M1AR = uint32_t(&dataPoints1); // Buffer 2
DMA2_Stream4->NDTR = maxSamples; // Number of transferred data
DMA2_Stream4->CR |= (0b01 << DMA_SxCR_PSIZE); // Source data size (00 = byte, 01 = half word, 10 = word)
DMA2_Stream4->CR |= (0b01 << DMA_SxCR_MSIZE); // Memory data size (00 = byte, 01 = half word, 10 = word)
DMA2_Stream4->CR |= DMA_SxCR_TCIE; // Transfer complete interrupt enable
DMA2_Stream4->CR |= DMA_SxCR_CIRC; // circular mode
DMA2_Stream4->CR &= ~DMA_SxCR_PINC; // no peripheral increment mode
DMA2_Stream4->CR |= DMA_SxCR_MINC; // memory increment mode
// DMA2_Stream4->CR |= DMA_SxCR_DBM; // double buffer mode
DMA2->HIFCR |= 0b111101; // clear flags
NVIC_EnableIRQ(DMA2_Stream4_IRQn);
delay(20);
DMA2_Stream4->CR |= DMA_SxCR_EN; // Enable
}
void loop() {
Serial.print(ADC1->DR);
Serial.print(" ");
Serial.print(dataPoints[0]);
Serial.print(" ");
Serial.print(dma_active);
Serial.print(" ");
Serial.println(DMA2_Stream4->NDTR);
delay(100);
}
void DMA2_Stream4_IRQHandler(void) {
dma_active = 0;
}
I used ADC+DMA on STM32F3's successfully, but I cannot get it to work on this F7.
The clock for GPIOA gets enabled, and PA3 is set to analog input.
The clock for the ADC gets enabled. The ADC is set to continuous mode with DMA mode and continuous DMA requests. The input is PA3. The ADC conversion is started.
The DMA stream 4 is set to the correct channel for ADC1 (channel 0). The input and output addresses are set as well as the number of data to transfer and the memory increment mode gets enabled. Then the stream gets enabled.
I am not sure what I step I am missing here.
I would really appreciate your help!
EDIT #2
I accidently mistook channel for stream and so I had the wrong channel selected for the DMA (channel 4 instead of channel 0 for ADC1 in DMA2 Stream 4). That was the main issue why it did not work.
Now it is working fine in double buffer mode, except for one thing:
When I enable the transfer complete interrupt, the program is no longer working. It is only writing one letter via Serial.print, the "s" from starting. No values are transmitted.
I made the interrupt so that it should just disable the DMA for now, but for some reason the interrupt seems to not work at all.
volatile static bool dma_active = 1;
#define maxSamples 512
int16_t dataPoints[maxSamples];
int16_t dataPoints2[maxSamples];
void setup() {
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN_Msk; // GPIOA clock enable
GPIOA->MODER |= (0b11 << GPIO_MODER_MODER3_Pos); // PA3 as analog input
Serial.begin(115200);
Serial.println("starting");
initDMA();
initADC();
}
void initADC() {
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN_Msk; // ADC1 clock enable
ADC1->CR2 |= ADC_CR2_ADON_Msk; // ADC on
ADC1->CR2 |= ADC_CR2_CONT_Msk; // continuous conversion mode
ADC1->CR1 |= ADC_CR1_EOCIE_Msk; // EOC interrupt
ADC1->CR1 &= ~(ADC_CR1_DISCEN_Msk); // discontinuous mode disabled
ADC1->CR1 &= ~(ADC_CR1_SCAN_Msk); // scan mode disabled
ADC1->CR2 |= ADC_CR2_DMA_Msk; // DMA mode
ADC1->CR2 |= ADC_CR2_DDS_Msk; // continuous DMA request
ADC1->SQR3 |= 0b11; // ADC1_IN3 = PA3
ADC1->SQR1 &= ~(0b1111 << ADC_SQR1_L_Pos); // 1 conversion
ADC1->CR2 |= ADC_CR2_SWSTART_Msk; // Start conversion
}
void initDMA() {
// DMA2 Stream4 : Channel 0 is ADC1
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN_Msk; // DMA2 clock enable
DMA2_Stream4->CR &= ~(DMA_SxCR_EN_Msk); // Disable
while (DMA2_Stream4->CR & (1 << 0));
DMA2->HIFCR |= 0b111101; // clear flags
DMA2_Stream4->CR |= (0b11 << DMA_SxCR_PL_Pos); // Very high priority
DMA2_Stream4->PAR = (uint32_t)&(ADC1->DR); // Data source register
DMA2_Stream4->M0AR = uint32_t(&dataPoints); // Buffer 1
DMA2_Stream4->M1AR = uint32_t(&dataPoints2); // Buffer 2
DMA2_Stream4->NDTR = maxSamples; // Number of transferred data
DMA2_Stream4->CR &= ~(0b1111 << DMA_SxCR_CHSEL_Pos); // Channel 4
DMA2_Stream4->CR |= (0b01 << DMA_SxCR_PSIZE_Pos); // Source data size (00 = byte, 01 = half word, 10 = word)
DMA2_Stream4->CR |= (0b01 << DMA_SxCR_MSIZE_Pos); // Memory data size (00 = byte, 01 = half word, 10 = word)
// DMA2_Stream4->CR |= DMA_SxCR_TCIE_Msk; // Transfer complete interrupt enable
// DMA2_Stream4->CR |= DMA_SxCR_CIRC_Msk; // circular mode
DMA2_Stream4->CR |= DMA_SxCR_DBM_Msk; // double buffer mode
DMA2_Stream4->CR &= ~(DMA_SxCR_PINC_Msk); // no peripheral increment mode
DMA2_Stream4->CR |= DMA_SxCR_MINC_Msk; // memory increment mode
NVIC_EnableIRQ(DMA2_Stream4_IRQn);
DMA2_Stream4->CR |= DMA_SxCR_EN_Msk; // Enable
}
void loop() {
for (int i = 0; i < maxSamples; i++)
{
Serial.print(dataPoints[i]);
Serial.print(" ");
// Serial.print(dataPoints2[i]);
Serial.print(" ");
Serial.print(dma_active);
Serial.println("");
}
delay(2000);
}
void DMA2_Stream4_IRQHandler(void) {
if ((DMA2->HISR) & DMA_HISR_TCIF4_Msk)
{
DMA2_Stream4->CR &= ~DMA_SxCR_EN_Msk; // Disable
dma_active = 0;
DMA2->HIFCR |= 0b111101; // clear flags
}
}
First of all you do not clear the interrupt flag and the interrupt is being called all the time.
Same errors:
ADC1->SQR1 &= ~(0b1111 << ADC_SQR1_L); does not cleat the L in the SQR1 register.
It should be ADC1->SQR1 &= ~(ADC_SQR1_L_Msk << ADC_SQR1_L_Pos);
Same error everywhere: (for example)
0b01 << DMA_SxCR_PSIZE
in my .h file DMA_SxCR_PSIZE is 0x00001800 :)
And many many more :)
It's due to D and I Cache. Disable it.
Maybe you can put DMA initialization before ADC initialization

uart transmit buffer ready signal getting stuck for serial transmission

terminal uart driver without interrupt enabled
void TerminalInit_polledio(int term_num)
{
int BAUD_RATE = 9600;
int divisor = 115200 / BAUD_RATE;
// first setup our vars
terminals[term_num].echo_mode = TRUE;
terminals[term_num].missed_intr = TRUE;
// Use a pair of sems. One limits available space in the output queue
// (terminal display), the other limits chars that are typed from the
// terminal. As part of initialization, the count of the output queue
// is set to the capacity of the char queue
// terminals[term_num].out_sid = SemInit(CHAR_Q_SIZE);
// a circular q, capacity CHAR_Q_SIZE
// terminals[term_num].in_sid = SemInit(0);
InitCharQ(&terminals[term_num].in_q); // initially empty
InitCharQ(&terminals[term_num].out_q); // initially empty
InitCharQ(&terminals[term_num].echo_q); // initially empty
// then setup the terminal for 7-E-1 at 9600 baud
// abbrevs:
// CFCR Char Format Control Reg, MSR Modem Status Reg, IIR Intr Indicator Reg
// MCR Modem Control Reg, IER Intr Enable Reg, LSR Line Status Reg
// ERXRDY Enable Recv Ready, ETXRDY Enable Xmit Ready
// LSR_TSRE Line Status Reg Xmit+Shift Regs Empty
outportb(terminals[term_num].io_base + CFCR, CFCR_DLAB); // CFCR_DLAB is 0x80
outportb(terminals[term_num].io_base + BAUDLO,LOBYTE(divisor));
outportb(terminals[term_num].io_base + BAUDHI,HIBYTE(divisor));
outportb(terminals[term_num].io_base + CFCR,CFCR_8BITS ); //8-N-1
outportb(terminals[term_num].io_base + IER,0);
// raise DTR & RTS of the serial port to start read/write
outportb(terminals[term_num].io_base + MCR, MCR_DTR | MCR_RTS | MCR_IENABLE);
outportb(terminals[term_num].io_base + IER,0);
//IO_DELAY();
//outportb(terminals[term_num].io_base + IER, IER_ERXRDY | IER_ETXRDY);
//IO_DELAY();
//FIFO stuff
outportb(terminals[term_num].io_base + FIFO, FIFO_ENABLE | FIFO_TRIGGER_8);
outportb(terminals[term_num].io_base + FIFO, FIFO_RCV_RESET | FIFO_XMT_RESET);
}
u8 get_serial_char_polledio() {
u8 status;
//printf("=>");
while(!(inportb(terminals[FT_TERM].io_base + LSR) & LSR_RXRDY)){
//cons_printf("%2.0x_",status);
}
return (inportb(terminals[FT_TERM].io_base + DATA) & 0x7F);
}
void put_serial_char_polledio(u8 ch) {
char status = inportb(terminals[FT_TERM].io_base + LSR) & LSR_TXRDY ;
while(!status) {
//cons_printf(" <%2.0x_%c> ",status,ch);
}
outportb(terminals[FT_TERM].io_base + DATA, ch);
inportb(terminals[FT_TERM].io_base + LSR) & LSR_TXRDY ;
// cons_printf(" <%2.0x_%c> ",status,ch);
}
void uart_out(){
char ch = 'A';
while(1){
put_serial_char_polledio(ch);
//printf("%c ",get_serial_char_polledio());
}
}
uart_out() is the method that gets dispatched and run as a process in my operating system, but after putting or transmitting char A for once, the process gets stalled and no more characters are put out. is there anything i am missing ?