3.2. Interactive Run

PikaScript supports reading strings directly to run Python scripts, so to support interactive operation, you only need to make a serial port receiving driver.

3.2.1.1. Implement a blocking byte read function

Interactive operation requires a low-level interface __platform_getchar() to read user input bytes. This interface is a weak function. Users need to implement a __platform_getchar() in their own code. to override this weak function. The weak function prototype is in PikaPlatform.c. If the user does not override it, an error will be reported when using the interactive runtime.

  1. /* PikaPlatform.c */
  2. PIKA_WEAK char __platform_getchar(void) {
  3. __platform_printf("[error]: __platform_getchar need impaltment!\r\n");
  4. while(1){
  5. }
  6. }

Users can directly implement a __platform_getchar() in the main.c of the project. If the platform itself supports getchar(), you can directly access the platform’s getchar().

  1. /* main.c */
  2. char __platform_getchar(){
  3. return getchar();
  4. }

If the platform does not support it, you need to implement it yourself, pay attention to implement a blocking getchar(), that is, when there is no serial input character, you need to use __platform_getchar() waits, and returns a character if there is input. E.g:

  1. /* main.c */
  2. char __platform_getchar(){
  3. char res = 0;
  4. while(rx_char == 0){
  5. };
  6. res = rx_char;
  7. rx_char = 0;
  8. return res;
  9. }

3.2.1.2. Start PikaScript Shell and run pikaScriptShell() directly to start interactive operation.

pikaScriptShell() The entry parameter is the root object of pika, and running pikaScriptInit() will create a root object.

  1. pikaScriptShell(pikaScriptInit());

3.2.1.3. Sample code

stm32g070cb: https://github.com/pikastech/pikascript/blob/master/bsp/stm32g070cb/Booter/main.c

rt-thread: https://github.com/pikastech/pikascript/blob/master/package/pikaRTThread/rt_pika.c

3.2.1.4. Precautions:

  • Kernel version needs to be at least v1.3.0

  • It is strongly recommended to use putty as a serial terminal.

_images/1641178790145-2f026e70-4ba1-4e9a-b05f-c602b2bd8cad.png

3.2.2. Option 2: Run by byte input

The obj_runChar kernel API can specify an object to execute a script with one byte of input.

You need to run obj_runCharInit() before you can use obj_runChar.

Example code.

  1. PikaObj* pikaMain = pikaScriptInit();
  2. obj_runCharInit(pikaMain);
  3. while(1){
  4. char ch = my_get_char();
  5. obj_runChar(pikaMain, ch);
  6. }

3.2.2.1. Caution.

Kernel version needs to be no less than v1.8.3

3.2.3. Option 3: Read and run the entire line

obj_run kernel API can specify an object to execute a script, and use this API to execute a single-line or multi-line script. The following is an example of the interactive running driver of CH32. This interactive running support is written in the main loop of the firmware and starts to execute after the pikaScriptInit() initialization script is executed.

  1. PikaObj *PikaMain = pikaScriptInit();
  2. printf(">>>");
  3. while(1)
  4. {
  5. if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET)
  6. {
  7. is_Rx_start = 1;
  8. t_start = rt_tick_get();
  9. rxCh = USART_ReceiveData(USART1);
  10. if(rxCh < 128){
  11. RxBuffer[RxCnt++] = rxCh;
  12. }
  13. }
  14. if( (is_Rx_start == 1) && (rt_tick_get() - t_start > 10) ){
  15. is_Rx_start = 0;
  16. for(int i = 0; i< RxCnt; i ++)
  17. {
  18. USART_SendData(USART1, RxBuffer[i]);
  19. while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)== RESET);
  20. }
  21. obj_run(PikaMain, RxBuffer);
  22. printf(">>>");
  23. memset(RxBuffer, 0, 256);
  24. RxCnt = 0;
  25. }
  26. }

3.2.3.1. Driven Content

  • Poll to receive characters and store them in the buffer.

  • A reception is considered complete when no new characters are received for more than 10ms. Using the idle time to determine the completion of the transmission of the string can support interactive running of multi-line scripts. If you only need to run the single-numbered script, you can use the newline character '\n' to determine the end of the string reception. When running a single-line script, the '\n' line break can be omitted, and a multi-line script needs to have a '\n' line break. Newlines of the form "\r\n" are also supported.

  • Echo the received string after receiving.

  • Execute scripts using the obj_run kernel API. The specified object is the root object created by the pikaScriptInit() init script, and the execution content is the received string.

  • Clean up the receive buffer.

3.2.3.2. Notes:

  • Kernel version needs to be at least v1.2.6

  • When executing a multi-line script, you need to pass in a complete code block For example: the following script is a complete code block, especially the 4th line, which needs to have an indent of 0 to mark the end of the code block. and the last line needs to have a blank line, which means print('the end') with a newline at the end of the script.

  1. while a < 10:
  2. a = a + 1
  3. print(a)
  4. print('the end')

The following example is also possible

  1. while a < 10:
  2. a = a + 1
  3. print(a)

The following example does not work

  1. # Missing final newline
  2. while a < 10:
  3. a = a + 1
  4. print(a)
  1. # The content of the while block is missing
  2. while a < 10: