Implement usart_block_sendrecv for STM32L432. Not tested.
This commit is contained in:
@@ -266,45 +266,48 @@ usart_main (void *arg)
|
||||
(void)arg;
|
||||
|
||||
for (i = 0; i < NUM_USART; i++)
|
||||
{
|
||||
*usart_array[i].tx_ready = 1;
|
||||
rb_init (usart_array[i].rb_a2h, usart_array[i].buf_a2h, BUF_A2H_SIZE);
|
||||
rb_init (usart_array[i].rb_h2a, usart_array[i].buf_h2a, BUF_H2A_SIZE);
|
||||
rb_get_prepare_poll (usart_array[i].rb_a2h, usart_array[i].app_write_event);
|
||||
}
|
||||
if (usart_array[i].tx_ready)
|
||||
{
|
||||
*usart_array[i].tx_ready = 1;
|
||||
rb_init (usart_array[i].rb_a2h, usart_array[i].buf_a2h, BUF_A2H_SIZE);
|
||||
rb_init (usart_array[i].rb_h2a, usart_array[i].buf_h2a, BUF_H2A_SIZE);
|
||||
rb_get_prepare_poll (usart_array[i].rb_a2h, usart_array[i].app_write_event);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for (i = 0; i < NUM_USART; i++)
|
||||
{
|
||||
usart_poll[n++] = (struct chx_poll_head *)usart_array[i].intr;
|
||||
if (*usart_array[i].tx_ready)
|
||||
usart_poll[n++] = (struct chx_poll_head *)usart_array[i].app_write_event;
|
||||
else
|
||||
usart_array[i].app_write_event->ready = 0;
|
||||
}
|
||||
if (usart_array[i].tx_ready)
|
||||
{
|
||||
usart_poll[n++] = (struct chx_poll_head *)usart_array[i].intr;
|
||||
if (*usart_array[i].tx_ready)
|
||||
usart_poll[n++] = (struct chx_poll_head *)usart_array[i].app_write_event;
|
||||
else
|
||||
usart_array[i].app_write_event->ready = 0;
|
||||
}
|
||||
|
||||
chopstx_poll (NULL, n, usart_poll);
|
||||
|
||||
for (i = 0; i < NUM_USART; i++)
|
||||
{
|
||||
int tx_done = 0;
|
||||
if (usart_array[i].tx_ready)
|
||||
{
|
||||
int tx_done = 0;
|
||||
|
||||
if (usart_array[i].intr->ready)
|
||||
{
|
||||
tx_done = handle_intr (usart_array[i].USART,
|
||||
usart_array[i].rb_h2a, usart_array[i].stat);
|
||||
*usart_array[i].tx_ready |= tx_done;
|
||||
chopstx_intr_done (usart_array[i].intr);
|
||||
}
|
||||
if (usart_array[i].intr->ready)
|
||||
{
|
||||
tx_done = handle_intr (usart_array[i].USART,
|
||||
usart_array[i].rb_h2a, usart_array[i].stat);
|
||||
*usart_array[i].tx_ready |= tx_done;
|
||||
chopstx_intr_done (usart_array[i].intr);
|
||||
}
|
||||
|
||||
if (tx_done || (*usart_array[i].tx_ready
|
||||
&& usart_array[i].app_write_event->ready))
|
||||
*usart_array[i].tx_ready = handle_tx (usart_array[i].USART,
|
||||
usart_array[i].rb_a2h, usart_array[i].stat);
|
||||
}
|
||||
if (tx_done || (*usart_array[i].tx_ready
|
||||
&& usart_array[i].app_write_event->ready))
|
||||
*usart_array[i].tx_ready = handle_tx (usart_array[i].USART,
|
||||
usart_array[i].rb_a2h, usart_array[i].stat);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -114,26 +114,26 @@ static int usart3_tx_ready;
|
||||
|
||||
struct usart {
|
||||
struct USART *USART;
|
||||
struct usart_stat *stat;
|
||||
struct chx_intr *intr;
|
||||
uint8_t irq_num;
|
||||
struct usart_stat *stat;
|
||||
struct rb *rb_a2h;
|
||||
struct rb *rb_h2a;
|
||||
uint8_t *buf_a2h;
|
||||
uint8_t *buf_h2a;
|
||||
chopstx_poll_cond_t *app_write_event;
|
||||
int *tx_ready;
|
||||
uint8_t irq_num;
|
||||
};
|
||||
|
||||
|
||||
static const struct usart usart_array[] =
|
||||
{
|
||||
{ USART2, &usart2_stat, &usart2_intr, &usart2_rb_a2h, &usart2_rb_h2a,
|
||||
buf_usart2_rb_a2h, buf_usart2_rb_h2a, &usart2_app_write_event,
|
||||
&usart2_tx_ready, INTR_REQ_USART2 },
|
||||
{ USART3, &usart3_stat, &usart3_intr, &usart3_rb_a2h, &usart3_rb_h2a,
|
||||
buf_usart3_rb_a2h, buf_usart3_rb_h2a, &usart3_app_write_event,
|
||||
&usart3_tx_ready, INTR_REQ_USART3 },
|
||||
{ USART2, &usart2_intr, INTR_REQ_USART3,
|
||||
&usart2_stat, &usart2_rb_a2h, &usart2_rb_h2a, buf_usart2_rb_a2h,
|
||||
buf_usart2_rb_h2a, &usart2_app_write_event, &usart2_tx_ready },
|
||||
{ USART3, &usart3_intr, INTR_REQ_USART3,
|
||||
&usart3_stat, &usart3_rb_a2h, &usart3_rb_h2a, buf_usart3_rb_a2h,
|
||||
buf_usart3_rb_h2a, &usart3_app_write_event, &usart3_tx_ready },
|
||||
};
|
||||
#define NUM_USART ((int)(sizeof (usart_array) / sizeof (struct usart)))
|
||||
|
||||
@@ -280,7 +280,8 @@ usart_init0 (int (*cb) (uint8_t dev_no, uint16_t notify_bits))
|
||||
|
||||
for (i = 0; i < NUM_USART; i++)
|
||||
{
|
||||
usart_array[i].stat->dev_no = i + USART_DEVNO_START;
|
||||
if (usart_array[i].stat)
|
||||
usart_array[i].stat->dev_no = i + USART_DEVNO_START;
|
||||
chopstx_claim_irq (usart_array[i].intr, usart_array[i].irq_num);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ struct USART {
|
||||
};
|
||||
|
||||
#define USART1_BASE (APB2PERIPH_BASE + 0x3800)
|
||||
#define USART1 ((struct USART *)USART1_BASE)
|
||||
|
||||
#define USART2_BASE (APB1PERIPH_BASE + 0x4400)
|
||||
#define USART2 ((struct USART *)USART2_BASE)
|
||||
@@ -61,6 +62,7 @@ struct USART {
|
||||
|
||||
static struct usart_stat usart2_stat;
|
||||
|
||||
static struct chx_intr usart1_intr;
|
||||
static struct chx_intr usart2_intr;
|
||||
|
||||
#define BUF_A2H_SIZE 256
|
||||
@@ -76,30 +78,36 @@ static chopstx_poll_cond_t usart2_app_write_event;
|
||||
/* Global variables so that it can be easier to debug. */
|
||||
static int usart2_tx_ready;
|
||||
|
||||
#define INTR_REQ_USART1 37
|
||||
#define INTR_REQ_USART2 38
|
||||
|
||||
#define USART_DEVNO_START 2
|
||||
#define USART_DEVNO_START 1
|
||||
#define USART_DEVNO_END 2
|
||||
|
||||
struct usart {
|
||||
struct USART *USART;
|
||||
struct usart_stat *stat;
|
||||
struct chx_intr *intr;
|
||||
uint8_t irq_num;
|
||||
struct usart_stat *stat;
|
||||
struct rb *rb_a2h;
|
||||
struct rb *rb_h2a;
|
||||
uint8_t *buf_a2h;
|
||||
uint8_t *buf_h2a;
|
||||
chopstx_poll_cond_t *app_write_event;
|
||||
int *tx_ready;
|
||||
uint8_t irq_num;
|
||||
};
|
||||
|
||||
|
||||
static const struct usart usart_array[] =
|
||||
{
|
||||
{ USART2, &usart2_stat, &usart2_intr, &usart2_rb_a2h, &usart2_rb_h2a,
|
||||
buf_usart2_rb_a2h, buf_usart2_rb_h2a, &usart2_app_write_event,
|
||||
&usart2_tx_ready, INTR_REQ_USART2 },
|
||||
{ USART1, &usart1_intr, INTR_REQ_USART1,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
},
|
||||
{ USART2, &usart2_intr, INTR_REQ_USART2,
|
||||
&usart2_stat, &usart2_rb_a2h, &usart2_rb_h2a, buf_usart2_rb_a2h,
|
||||
buf_usart2_rb_h2a, &usart2_app_write_event, &usart2_tx_ready,
|
||||
},
|
||||
};
|
||||
#define NUM_USART ((int)(sizeof (usart_array) / sizeof (struct usart)))
|
||||
|
||||
@@ -243,13 +251,19 @@ usart_init0 (int (*cb) (uint8_t dev_no, uint16_t notify_bits))
|
||||
|
||||
for (i = 0; i < NUM_USART; i++)
|
||||
{
|
||||
usart_array[i].stat->dev_no = i + USART_DEVNO_START;
|
||||
if (usart_array[i].stat)
|
||||
usart_array[i].stat->dev_no = i + USART_DEVNO_START;
|
||||
chopstx_claim_irq (usart_array[i].intr, usart_array[i].irq_num);
|
||||
}
|
||||
|
||||
/* Enable USART1 clock, and strobe reset. */
|
||||
RCC->APB2ENR |= RCC_APB2_USART1;
|
||||
RCC->APB2RSTR = RCC_APB2_USART1;
|
||||
RCC->APB2RSTR = 0;
|
||||
|
||||
/* Enable USART2 clock, and strobe reset. */
|
||||
RCC->APB1ENR1 |= (1 << 17);
|
||||
RCC->APB1RSTR1 = (1 << 17);
|
||||
RCC->APB1ENR1 |= RCC_APB1_1_USART2;
|
||||
RCC->APB1RSTR1 = RCC_APB1_1_USART2;
|
||||
RCC->APB1RSTR1 = 0;
|
||||
}
|
||||
|
||||
@@ -383,6 +397,11 @@ usart_send_break (uint8_t dev_no)
|
||||
if (USARTx == NULL)
|
||||
return -1;
|
||||
|
||||
if ((USARTx->ISR & (1 << 18)))
|
||||
return 1; /* Busy sending break, which was requested before. */
|
||||
|
||||
/* ??? Should we check TX is empty? */
|
||||
|
||||
USARTx->RQR |= 0x02;
|
||||
return 0;
|
||||
}
|
||||
@@ -392,13 +411,131 @@ usart_block_sendrecv (uint8_t dev_no, const char *s_buf, uint16_t s_buflen,
|
||||
char *r_buf, uint16_t r_buflen,
|
||||
uint32_t *timeout_block_p, uint32_t timeout_char)
|
||||
{
|
||||
/* TBD */
|
||||
(void)dev_no;
|
||||
(void)s_buf;
|
||||
(void)s_buflen;
|
||||
(void)r_buf;
|
||||
(void)r_buflen;
|
||||
(void)timeout_block_p;
|
||||
(void)timeout_char;
|
||||
return 0;
|
||||
uint32_t timeout;
|
||||
uint8_t *p;
|
||||
int len;
|
||||
uint32_t r;
|
||||
uint32_t data;
|
||||
struct USART *USARTx = get_usart_dev (dev_no);
|
||||
int smartcard_mode = ((USARTx->CR3 & USART_CR3_SCEN) != 0);
|
||||
struct chx_intr *usartx_intr = get_usart_intr (dev_no);
|
||||
struct chx_poll_head *ph[1];
|
||||
|
||||
if (usartx_intr == NULL)
|
||||
return -1;
|
||||
|
||||
ph[0] = (struct chx_poll_head *)usartx_intr;
|
||||
|
||||
p = (uint8_t *)s_buf;
|
||||
if (p)
|
||||
{
|
||||
if (smartcard_mode)
|
||||
usart_config_recv_enable (USARTx, 0);
|
||||
|
||||
USARTx->CR1 |= USART_CR1_TXEIE;
|
||||
|
||||
/* Sending part */
|
||||
while (1)
|
||||
{
|
||||
chopstx_poll (NULL, 1, ph);
|
||||
|
||||
r = USARTx->ISR;
|
||||
|
||||
/* Here, ignore recv error(s). */
|
||||
if ((r & USART_ISR_RXNE) || (r & USART_ISR_ORE))
|
||||
{
|
||||
data = USARTx->RDR;
|
||||
asm volatile ("" : : "r" (data) : "memory");
|
||||
}
|
||||
|
||||
if ((r & USART_ISR_TXE))
|
||||
{
|
||||
if (s_buflen == 0)
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* Keep TXEIE bit */
|
||||
USARTx->TDR = *p++;
|
||||
s_buflen--;
|
||||
}
|
||||
}
|
||||
|
||||
chopstx_intr_done (usartx_intr);
|
||||
}
|
||||
|
||||
USARTx->CR1 &= ~USART_CR1_TXEIE;
|
||||
if (smartcard_mode)
|
||||
{
|
||||
if ((*timeout_block_p))
|
||||
do
|
||||
r = USARTx->ISR;
|
||||
while (((r & USART_ISR_TC) == 0));
|
||||
usart_config_recv_enable (USARTx, 1);
|
||||
|
||||
if (*timeout_block_p == 0)
|
||||
{
|
||||
/* Ignoring the echo back. */
|
||||
do
|
||||
r = USARTx->ISR;
|
||||
while (((r & USART_ISR_TC) == 0));
|
||||
|
||||
if ((r & USART_ISR_RXNE))
|
||||
{
|
||||
data = USARTx->RDR;
|
||||
asm volatile ("" : : "r" (data) : "memory");
|
||||
}
|
||||
|
||||
*timeout_block_p = timeout_char;
|
||||
}
|
||||
}
|
||||
|
||||
chopstx_intr_done (usartx_intr);
|
||||
}
|
||||
|
||||
/* Receiving part */
|
||||
r = chopstx_poll (timeout_block_p, 1, ph);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
p = (uint8_t *)r_buf;
|
||||
len = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
r = USARTx->ISR;
|
||||
|
||||
data = USARTx->RDR;
|
||||
asm volatile ("" : : "r" (data) : "memory");
|
||||
|
||||
if ((r & USART_ISR_RXNE))
|
||||
{
|
||||
if ((r & USART_ISR_NE) || (r & USART_ISR_FE) || (r & USART_ISR_PE))
|
||||
/* ignore error, for now. XXX: ss_notify */
|
||||
;
|
||||
else
|
||||
{
|
||||
*p++ = (data & 0xff);
|
||||
len++;
|
||||
r_buflen--;
|
||||
if (r_buflen == 0)
|
||||
{
|
||||
chopstx_intr_done (usartx_intr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((r & USART_ISR_ORE))
|
||||
{
|
||||
data = USARTx->RDR;
|
||||
asm volatile ("" : : "r" (data) : "memory");
|
||||
}
|
||||
|
||||
chopstx_intr_done (usartx_intr);
|
||||
timeout = timeout_char;
|
||||
r = chopstx_poll (&timeout, 1, ph);
|
||||
if (r == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user