mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Tue Jul 29 19:00:07 2014 +0100
Revision:
268:402bcc0c870b
Parent:
227:7bd0639b8911
Child:
497:d54623194236
Synchronized with git revision 490d1a6606b3138f165c5edf2f2370ca616587c0

Full URL: https://github.com/mbedmicro/mbed/commit/490d1a6606b3138f165c5edf2f2370ca616587c0/

[LPC1114] Sleep fix + some device.h settings

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 126:549ba18ddd81 1 /* mbed Microcontroller Library
mbed_official 126:549ba18ddd81 2 *******************************************************************************
mbed_official 126:549ba18ddd81 3 * Copyright (c) 2014, STMicroelectronics
mbed_official 126:549ba18ddd81 4 * All rights reserved.
mbed_official 126:549ba18ddd81 5 *
mbed_official 126:549ba18ddd81 6 * Redistribution and use in source and binary forms, with or without
mbed_official 126:549ba18ddd81 7 * modification, are permitted provided that the following conditions are met:
mbed_official 126:549ba18ddd81 8 *
mbed_official 126:549ba18ddd81 9 * 1. Redistributions of source code must retain the above copyright notice,
mbed_official 126:549ba18ddd81 10 * this list of conditions and the following disclaimer.
mbed_official 126:549ba18ddd81 11 * 2. Redistributions in binary form must reproduce the above copyright notice,
mbed_official 126:549ba18ddd81 12 * this list of conditions and the following disclaimer in the documentation
mbed_official 126:549ba18ddd81 13 * and/or other materials provided with the distribution.
mbed_official 126:549ba18ddd81 14 * 3. Neither the name of STMicroelectronics nor the names of its contributors
mbed_official 126:549ba18ddd81 15 * may be used to endorse or promote products derived from this software
mbed_official 126:549ba18ddd81 16 * without specific prior written permission.
mbed_official 126:549ba18ddd81 17 *
mbed_official 126:549ba18ddd81 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
mbed_official 126:549ba18ddd81 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
mbed_official 126:549ba18ddd81 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
mbed_official 126:549ba18ddd81 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
mbed_official 126:549ba18ddd81 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
mbed_official 126:549ba18ddd81 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
mbed_official 126:549ba18ddd81 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
mbed_official 126:549ba18ddd81 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
mbed_official 126:549ba18ddd81 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
mbed_official 126:549ba18ddd81 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
mbed_official 126:549ba18ddd81 28 *******************************************************************************
mbed_official 126:549ba18ddd81 29 */
mbed_official 227:7bd0639b8911 30 #include "mbed_assert.h"
mbed_official 126:549ba18ddd81 31 #include "serial_api.h"
mbed_official 126:549ba18ddd81 32 #include "cmsis.h"
mbed_official 126:549ba18ddd81 33 #include "pinmap.h"
mbed_official 126:549ba18ddd81 34 #include <string.h>
mbed_official 126:549ba18ddd81 35
mbed_official 126:549ba18ddd81 36 static const PinMap PinMap_UART_TX[] = {
mbed_official 165:46e3636d4af7 37 {PA_9, UART_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
mbed_official 165:46e3636d4af7 38 {PA_2, UART_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
mbed_official 165:46e3636d4af7 39 {PB_10, UART_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
mbed_official 165:46e3636d4af7 40 {NC, NC, 0}
mbed_official 126:549ba18ddd81 41 };
mbed_official 126:549ba18ddd81 42
mbed_official 126:549ba18ddd81 43 static const PinMap PinMap_UART_RX[] = {
mbed_official 165:46e3636d4af7 44 {PA_10, UART_1, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 0)},
mbed_official 165:46e3636d4af7 45 {PA_3, UART_2, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 0)},
mbed_official 165:46e3636d4af7 46 {PB_11, UART_3, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 0)},
mbed_official 165:46e3636d4af7 47 {NC, NC, 0}
mbed_official 126:549ba18ddd81 48 };
mbed_official 126:549ba18ddd81 49
mbed_official 165:46e3636d4af7 50 #define UART_NUM (3)
mbed_official 126:549ba18ddd81 51
mbed_official 165:46e3636d4af7 52 static uint32_t serial_irq_ids[UART_NUM] = {0,0,0};
mbed_official 126:549ba18ddd81 53
mbed_official 126:549ba18ddd81 54 static uart_irq_handler irq_handler;
mbed_official 126:549ba18ddd81 55
mbed_official 126:549ba18ddd81 56 int stdio_uart_inited = 0;
mbed_official 126:549ba18ddd81 57 serial_t stdio_uart;
mbed_official 126:549ba18ddd81 58
mbed_official 126:549ba18ddd81 59 static void init_usart(serial_t *obj) {
mbed_official 126:549ba18ddd81 60 USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
mbed_official 126:549ba18ddd81 61 USART_InitTypeDef USART_InitStructure;
mbed_official 126:549ba18ddd81 62
mbed_official 126:549ba18ddd81 63 USART_Cmd(usart, DISABLE);
mbed_official 126:549ba18ddd81 64
mbed_official 126:549ba18ddd81 65 USART_InitStructure.USART_BaudRate = obj->baudrate;
mbed_official 126:549ba18ddd81 66 USART_InitStructure.USART_WordLength = obj->databits;
mbed_official 126:549ba18ddd81 67 USART_InitStructure.USART_StopBits = obj->stopbits;
mbed_official 126:549ba18ddd81 68 USART_InitStructure.USART_Parity = obj->parity;
mbed_official 126:549ba18ddd81 69 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
mbed_official 126:549ba18ddd81 70 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
mbed_official 126:549ba18ddd81 71 USART_Init(usart, &USART_InitStructure);
mbed_official 126:549ba18ddd81 72
mbed_official 126:549ba18ddd81 73 USART_Cmd(usart, ENABLE);
mbed_official 126:549ba18ddd81 74 }
mbed_official 126:549ba18ddd81 75
mbed_official 227:7bd0639b8911 76 void serial_init(serial_t *obj, PinName tx, PinName rx) {
mbed_official 126:549ba18ddd81 77 // Determine the UART to use (UART_1, UART_2, ...)
mbed_official 126:549ba18ddd81 78 UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
mbed_official 126:549ba18ddd81 79 UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
mbed_official 126:549ba18ddd81 80
mbed_official 126:549ba18ddd81 81 // Get the peripheral name (UART_1, UART_2, ...) from the pin and assign it to the object
mbed_official 126:549ba18ddd81 82 obj->uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
mbed_official 227:7bd0639b8911 83 MBED_ASSERT(obj->uart != (UARTName)NC);
mbed_official 126:549ba18ddd81 84
mbed_official 126:549ba18ddd81 85 // Enable USART clock
mbed_official 126:549ba18ddd81 86 if (obj->uart == UART_1) {
mbed_official 227:7bd0639b8911 87 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
mbed_official 165:46e3636d4af7 88 } else if (obj->uart == UART_2 ) {
mbed_official 165:46e3636d4af7 89 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
mbed_official 165:46e3636d4af7 90 } else if (obj->uart == UART_3 ) {
mbed_official 165:46e3636d4af7 91 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
mbed_official 126:549ba18ddd81 92 }
mbed_official 126:549ba18ddd81 93
mbed_official 126:549ba18ddd81 94 // Configure the UART pins
mbed_official 126:549ba18ddd81 95 pinmap_pinout(tx, PinMap_UART_TX);
mbed_official 126:549ba18ddd81 96 pinmap_pinout(rx, PinMap_UART_RX);
mbed_official 126:549ba18ddd81 97
mbed_official 126:549ba18ddd81 98 // Configure UART
mbed_official 126:549ba18ddd81 99 obj->baudrate = 9600;
mbed_official 126:549ba18ddd81 100 obj->databits = USART_WordLength_8b;
mbed_official 126:549ba18ddd81 101 obj->stopbits = USART_StopBits_1;
mbed_official 227:7bd0639b8911 102 obj->parity = USART_Parity_No;
mbed_official 126:549ba18ddd81 103
mbed_official 126:549ba18ddd81 104 init_usart(obj);
mbed_official 126:549ba18ddd81 105
mbed_official 126:549ba18ddd81 106 // The index is used by irq
mbed_official 126:549ba18ddd81 107 if (obj->uart == UART_1) obj->index = 0;
mbed_official 126:549ba18ddd81 108 if (obj->uart == UART_2) obj->index = 1;
mbed_official 165:46e3636d4af7 109 if (obj->uart == UART_3) obj->index = 2;
mbed_official 126:549ba18ddd81 110
mbed_official 126:549ba18ddd81 111 // For stdio management
mbed_official 126:549ba18ddd81 112 if (obj->uart == STDIO_UART) {
mbed_official 126:549ba18ddd81 113 stdio_uart_inited = 1;
mbed_official 126:549ba18ddd81 114 memcpy(&stdio_uart, obj, sizeof(serial_t));
mbed_official 126:549ba18ddd81 115 }
mbed_official 126:549ba18ddd81 116
mbed_official 126:549ba18ddd81 117 }
mbed_official 126:549ba18ddd81 118
mbed_official 126:549ba18ddd81 119 void serial_free(serial_t *obj) {
mbed_official 126:549ba18ddd81 120 serial_irq_ids[obj->index] = 0;
mbed_official 126:549ba18ddd81 121 }
mbed_official 126:549ba18ddd81 122
mbed_official 126:549ba18ddd81 123 void serial_baud(serial_t *obj, int baudrate) {
mbed_official 126:549ba18ddd81 124 obj->baudrate = baudrate;
mbed_official 126:549ba18ddd81 125 init_usart(obj);
mbed_official 126:549ba18ddd81 126 }
mbed_official 126:549ba18ddd81 127
mbed_official 126:549ba18ddd81 128 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
mbed_official 126:549ba18ddd81 129 if (data_bits == 8) {
mbed_official 126:549ba18ddd81 130 obj->databits = USART_WordLength_8b;
mbed_official 126:549ba18ddd81 131 }
mbed_official 126:549ba18ddd81 132 else {
mbed_official 126:549ba18ddd81 133 obj->databits = USART_WordLength_9b;
mbed_official 126:549ba18ddd81 134 }
mbed_official 126:549ba18ddd81 135
mbed_official 126:549ba18ddd81 136 switch (parity) {
mbed_official 126:549ba18ddd81 137 case ParityOdd:
mbed_official 126:549ba18ddd81 138 case ParityForced0:
mbed_official 126:549ba18ddd81 139 obj->parity = USART_Parity_Odd;
mbed_official 126:549ba18ddd81 140 break;
mbed_official 126:549ba18ddd81 141 case ParityEven:
mbed_official 227:7bd0639b8911 142 case ParityForced1:
mbed_official 126:549ba18ddd81 143 obj->parity = USART_Parity_Even;
mbed_official 126:549ba18ddd81 144 break;
mbed_official 126:549ba18ddd81 145 default: // ParityNone
mbed_official 126:549ba18ddd81 146 obj->parity = USART_Parity_No;
mbed_official 126:549ba18ddd81 147 break;
mbed_official 126:549ba18ddd81 148 }
mbed_official 126:549ba18ddd81 149
mbed_official 126:549ba18ddd81 150 if (stop_bits == 2) {
mbed_official 126:549ba18ddd81 151 obj->stopbits = USART_StopBits_2;
mbed_official 126:549ba18ddd81 152 }
mbed_official 126:549ba18ddd81 153 else {
mbed_official 126:549ba18ddd81 154 obj->stopbits = USART_StopBits_1;
mbed_official 126:549ba18ddd81 155 }
mbed_official 126:549ba18ddd81 156
mbed_official 126:549ba18ddd81 157 init_usart(obj);
mbed_official 126:549ba18ddd81 158 }
mbed_official 126:549ba18ddd81 159
mbed_official 126:549ba18ddd81 160 /******************************************************************************
mbed_official 126:549ba18ddd81 161 * INTERRUPTS HANDLING
mbed_official 126:549ba18ddd81 162 ******************************************************************************/
mbed_official 126:549ba18ddd81 163
mbed_official 126:549ba18ddd81 164 // not api
mbed_official 126:549ba18ddd81 165 static void uart_irq(USART_TypeDef* usart, int id) {
mbed_official 126:549ba18ddd81 166 if (serial_irq_ids[id] != 0) {
mbed_official 126:549ba18ddd81 167 if (USART_GetITStatus(usart, USART_IT_TC) != RESET) {
mbed_official 126:549ba18ddd81 168 irq_handler(serial_irq_ids[id], TxIrq);
mbed_official 126:549ba18ddd81 169 USART_ClearITPendingBit(usart, USART_IT_TC);
mbed_official 126:549ba18ddd81 170 }
mbed_official 126:549ba18ddd81 171 if (USART_GetITStatus(usart, USART_IT_RXNE) != RESET) {
mbed_official 126:549ba18ddd81 172 irq_handler(serial_irq_ids[id], RxIrq);
mbed_official 126:549ba18ddd81 173 USART_ClearITPendingBit(usart, USART_IT_RXNE);
mbed_official 126:549ba18ddd81 174 }
mbed_official 126:549ba18ddd81 175 }
mbed_official 126:549ba18ddd81 176 }
mbed_official 126:549ba18ddd81 177
mbed_official 126:549ba18ddd81 178 static void uart1_irq(void) {uart_irq((USART_TypeDef*)UART_1, 0);}
mbed_official 126:549ba18ddd81 179 static void uart2_irq(void) {uart_irq((USART_TypeDef*)UART_2, 1);}
mbed_official 165:46e3636d4af7 180 static void uart3_irq(void) {uart_irq((USART_TypeDef*)UART_3, 2);}
mbed_official 126:549ba18ddd81 181
mbed_official 126:549ba18ddd81 182 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
mbed_official 126:549ba18ddd81 183 irq_handler = handler;
mbed_official 126:549ba18ddd81 184 serial_irq_ids[obj->index] = id;
mbed_official 126:549ba18ddd81 185 }
mbed_official 126:549ba18ddd81 186
mbed_official 126:549ba18ddd81 187 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
mbed_official 126:549ba18ddd81 188 IRQn_Type irq_n = (IRQn_Type)0;
mbed_official 126:549ba18ddd81 189 uint32_t vector = 0;
mbed_official 126:549ba18ddd81 190 USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
mbed_official 126:549ba18ddd81 191
mbed_official 126:549ba18ddd81 192 if (obj->uart == UART_1) {
mbed_official 126:549ba18ddd81 193 irq_n = USART1_IRQn;
mbed_official 126:549ba18ddd81 194 vector = (uint32_t)&uart1_irq;
mbed_official 126:549ba18ddd81 195 }
mbed_official 126:549ba18ddd81 196
mbed_official 126:549ba18ddd81 197 if (obj->uart == UART_2) {
mbed_official 126:549ba18ddd81 198 irq_n = USART2_IRQn;
mbed_official 126:549ba18ddd81 199 vector = (uint32_t)&uart2_irq;
mbed_official 126:549ba18ddd81 200 }
mbed_official 165:46e3636d4af7 201
mbed_official 165:46e3636d4af7 202 if (obj->uart == UART_3) {
mbed_official 165:46e3636d4af7 203 irq_n = USART3_IRQn;
mbed_official 165:46e3636d4af7 204 vector = (uint32_t)&uart3_irq;
mbed_official 165:46e3636d4af7 205 }
mbed_official 165:46e3636d4af7 206
mbed_official 126:549ba18ddd81 207 if (enable) {
mbed_official 126:549ba18ddd81 208
mbed_official 126:549ba18ddd81 209 if (irq == RxIrq) {
mbed_official 126:549ba18ddd81 210 USART_ITConfig(usart, USART_IT_RXNE, ENABLE);
mbed_official 126:549ba18ddd81 211 }
mbed_official 126:549ba18ddd81 212 else { // TxIrq
mbed_official 126:549ba18ddd81 213 USART_ITConfig(usart, USART_IT_TC, ENABLE);
mbed_official 227:7bd0639b8911 214 }
mbed_official 126:549ba18ddd81 215
mbed_official 126:549ba18ddd81 216 NVIC_SetVector(irq_n, vector);
mbed_official 126:549ba18ddd81 217 NVIC_EnableIRQ(irq_n);
mbed_official 126:549ba18ddd81 218
mbed_official 126:549ba18ddd81 219 } else { // disable
mbed_official 126:549ba18ddd81 220
mbed_official 126:549ba18ddd81 221 int all_disabled = 0;
mbed_official 126:549ba18ddd81 222
mbed_official 126:549ba18ddd81 223 if (irq == RxIrq) {
mbed_official 126:549ba18ddd81 224 USART_ITConfig(usart, USART_IT_RXNE, DISABLE);
mbed_official 126:549ba18ddd81 225 // Check if TxIrq is disabled too
mbed_official 126:549ba18ddd81 226 if ((usart->CR1 & USART_CR1_TXEIE) == 0) all_disabled = 1;
mbed_official 126:549ba18ddd81 227 }
mbed_official 126:549ba18ddd81 228 else { // TxIrq
mbed_official 126:549ba18ddd81 229 USART_ITConfig(usart, USART_IT_TXE, DISABLE);
mbed_official 126:549ba18ddd81 230 // Check if RxIrq is disabled too
mbed_official 227:7bd0639b8911 231 if ((usart->CR1 & USART_CR1_RXNEIE) == 0) all_disabled = 1;
mbed_official 126:549ba18ddd81 232 }
mbed_official 126:549ba18ddd81 233
mbed_official 126:549ba18ddd81 234 if (all_disabled) NVIC_DisableIRQ(irq_n);
mbed_official 126:549ba18ddd81 235
mbed_official 227:7bd0639b8911 236 }
mbed_official 126:549ba18ddd81 237 }
mbed_official 126:549ba18ddd81 238
mbed_official 126:549ba18ddd81 239 /******************************************************************************
mbed_official 126:549ba18ddd81 240 * READ/WRITE
mbed_official 126:549ba18ddd81 241 ******************************************************************************/
mbed_official 126:549ba18ddd81 242
mbed_official 126:549ba18ddd81 243 int serial_getc(serial_t *obj) {
mbed_official 126:549ba18ddd81 244 USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
mbed_official 126:549ba18ddd81 245 while (!serial_readable(obj));
mbed_official 126:549ba18ddd81 246 return (int)(USART_ReceiveData(usart));
mbed_official 126:549ba18ddd81 247 }
mbed_official 126:549ba18ddd81 248
mbed_official 126:549ba18ddd81 249 void serial_putc(serial_t *obj, int c) {
mbed_official 126:549ba18ddd81 250 USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
mbed_official 126:549ba18ddd81 251 while (!serial_writable(obj));
mbed_official 126:549ba18ddd81 252 USART_SendData(usart, (uint16_t)c);
mbed_official 126:549ba18ddd81 253 }
mbed_official 126:549ba18ddd81 254
mbed_official 126:549ba18ddd81 255 int serial_readable(serial_t *obj) {
mbed_official 126:549ba18ddd81 256 int status;
mbed_official 126:549ba18ddd81 257 USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
mbed_official 126:549ba18ddd81 258 // Check if data is received
mbed_official 126:549ba18ddd81 259 status = ((USART_GetFlagStatus(usart, USART_FLAG_RXNE) != RESET) ? 1 : 0);
mbed_official 126:549ba18ddd81 260 return status;
mbed_official 126:549ba18ddd81 261 }
mbed_official 126:549ba18ddd81 262
mbed_official 126:549ba18ddd81 263 int serial_writable(serial_t *obj) {
mbed_official 126:549ba18ddd81 264 int status;
mbed_official 126:549ba18ddd81 265 USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
mbed_official 126:549ba18ddd81 266 // Check if data is transmitted
mbed_official 126:549ba18ddd81 267 status = ((USART_GetFlagStatus(usart, USART_FLAG_TXE) != RESET) ? 1 : 0);
mbed_official 126:549ba18ddd81 268 return status;
mbed_official 126:549ba18ddd81 269 }
mbed_official 126:549ba18ddd81 270
mbed_official 126:549ba18ddd81 271 void serial_clear(serial_t *obj) {
mbed_official 126:549ba18ddd81 272 USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
mbed_official 126:549ba18ddd81 273 USART_ClearFlag(usart, USART_FLAG_TXE);
mbed_official 126:549ba18ddd81 274 USART_ClearFlag(usart, USART_FLAG_RXNE);
mbed_official 126:549ba18ddd81 275 }
mbed_official 126:549ba18ddd81 276
mbed_official 126:549ba18ddd81 277 void serial_pinout_tx(PinName tx) {
mbed_official 126:549ba18ddd81 278 pinmap_pinout(tx, PinMap_UART_TX);
mbed_official 126:549ba18ddd81 279 }
mbed_official 126:549ba18ddd81 280
mbed_official 126:549ba18ddd81 281 void serial_break_set(serial_t *obj) {
mbed_official 126:549ba18ddd81 282 USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
mbed_official 126:549ba18ddd81 283 USART_SendBreak(usart);
mbed_official 126:549ba18ddd81 284 }
mbed_official 126:549ba18ddd81 285
mbed_official 126:549ba18ddd81 286 void serial_break_clear(serial_t *obj) {
mbed_official 126:549ba18ddd81 287 }