i2c_hw_slave.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. #include "module.h"
  2. #include "lauxlib.h"
  3. #include "lextra.h"
  4. #include "lmem.h"
  5. #include "driver/i2c.h"
  6. #include "i2c_common.h"
  7. #include "freertos/FreeRTOS.h"
  8. #include "freertos/task.h"
  9. #include "freertos/queue.h"
  10. #include "esp_task.h"
  11. #include "task/task.h"
  12. #include <string.h>
  13. #define DEFAULT_BUF_LEN 128
  14. #define I2C_SLAVE_DEFAULT_RXBUF_LEN DEFAULT_BUF_LEN
  15. #define I2C_SLAVE_DEFAULT_TXBUF_LEN DEFAULT_BUF_LEN
  16. // user data descriptor for a port
  17. typedef struct {
  18. unsigned port;
  19. size_t rxbuf_len;
  20. TaskHandle_t xReceiveTaskHandle;
  21. int receivedcb_ref;
  22. } i2c_hw_slave_ud_type;
  23. // read data descriptor
  24. // it's used as variable length data block, filled by the i2c driver during read
  25. typedef struct {
  26. size_t len;
  27. uint8_t data[1];
  28. } i2c_read_type;
  29. // job descriptor
  30. // contains all information for the transfer task and subsequent result task
  31. // to process the transfer
  32. typedef struct {
  33. unsigned port;
  34. esp_err_t err;
  35. int receivedcb_ref;
  36. i2c_read_type *read_data;
  37. } i2c_job_desc_type;
  38. // the global variables for storing userdata for each I2C port
  39. static i2c_hw_slave_ud_type i2c_hw_slave_ud[I2C_NUM_MAX];
  40. // Receive task handle and job queue
  41. static task_handle_t i2c_receive_task_id;
  42. // Receive Task, FreeRTOS layer
  43. // This is a fully-fledged FreeRTOS task which runs concurrently and waits
  44. // for data from the I2C master using i2c_slave_read_buffer which blocks this task.
  45. // Received data is posted as a job to the NodeMCU layer task.
  46. //
  47. static void vReceiveTask( void *pvParameters )
  48. {
  49. i2c_hw_slave_ud_type *ud = (i2c_hw_slave_ud_type *)pvParameters;
  50. i2c_job_desc_type *job;
  51. i2c_read_type *read_data;
  52. for (;;) {
  53. job = (i2c_job_desc_type *)malloc( sizeof( i2c_job_desc_type ) );
  54. read_data = (i2c_read_type *)malloc( sizeof( i2c_read_type ) + ud->rxbuf_len-1 );
  55. if (!job || !read_data) {
  56. // shut down this task in case of memory shortage
  57. vTaskSuspend( NULL );
  58. }
  59. job->read_data = read_data;
  60. int size = i2c_slave_read_buffer( ud->port, job->read_data->data, ud->rxbuf_len, portMAX_DELAY );
  61. if (size >= 0) {
  62. job->read_data->len = size;
  63. job->err = 0;
  64. } else {
  65. job->read_data->len = 0;
  66. job->err = size;
  67. }
  68. job->port = ud->port;
  69. job->receivedcb_ref = ud->receivedcb_ref;
  70. task_post_medium( i2c_receive_task_id, (task_param_t)job );
  71. }
  72. }
  73. // Receive Task, NodeMCU layer
  74. // Is posted by the FreeRTOS layer and triggers the Lua callback with
  75. // read result data.
  76. //
  77. static void i2c_receive_task( task_param_t param, task_prio_t prio )
  78. {
  79. i2c_job_desc_type *job = (i2c_job_desc_type *)param;
  80. lua_State *L = lua_getstate();
  81. if (job->receivedcb_ref != LUA_NOREF) {
  82. lua_rawgeti( L, LUA_REGISTRYINDEX, job->receivedcb_ref );
  83. lua_pushinteger( L, job->err );
  84. if (job->read_data->len) {
  85. // all fine, deliver read data
  86. lua_pushlstring( L, (char *)job->read_data->data, job->read_data->len );
  87. } else {
  88. lua_pushnil( L );
  89. }
  90. lua_call(L, 2, 0);
  91. }
  92. // free all memory
  93. free( job->read_data );
  94. free( job );
  95. }
  96. static int i2c_lua_checkerr( lua_State *L, esp_err_t err ) {
  97. const char *msg;
  98. switch (err) {
  99. case ESP_OK: return 0;
  100. case ESP_FAIL: msg = "command failed"; break;
  101. case ESP_ERR_INVALID_ARG: msg = "parameter error"; break;
  102. case ESP_ERR_INVALID_STATE: msg = "driver state error"; break;
  103. case ESP_ERR_TIMEOUT: msg = "timeout"; break;
  104. default: msg = "unknown error"; break;
  105. }
  106. return luaL_error( L, msg );
  107. }
  108. #define get_udata(L) \
  109. unsigned port = luaL_checkint( L, 1 ) - I2C_ID_HW0; \
  110. luaL_argcheck( L, port < I2C_NUM_MAX, 1, "invalid hardware id" ); \
  111. i2c_hw_slave_ud_type *ud = &(i2c_hw_slave_ud[port]);
  112. // Set up FreeRTOS task and queue
  113. // Prepares the gory tasking stuff.
  114. //
  115. static int setup_rtos_task( i2c_hw_slave_ud_type *ud, unsigned port )
  116. {
  117. char pcName[configMAX_TASK_NAME_LEN+1];
  118. snprintf( pcName, configMAX_TASK_NAME_LEN+1, "I2C_Slave_%d", port );
  119. pcName[configMAX_TASK_NAME_LEN] = '\0';
  120. // create task with higher priority
  121. BaseType_t xReturned = xTaskCreate( vReceiveTask,
  122. pcName,
  123. 1024,
  124. (void *)ud,
  125. ESP_TASK_MAIN_PRIO + 1,
  126. &(ud->xReceiveTaskHandle) );
  127. if (xReturned != pdPASS) {
  128. return 0;
  129. }
  130. return 1;
  131. }
  132. // Set up the HW as master interface
  133. // Cares for I2C driver creation and initialization.
  134. //
  135. static int li2c_slave_setup( lua_State *L )
  136. {
  137. get_udata(L);
  138. ud->port = port;
  139. int stack = 1;
  140. luaL_checkanytable( L, ++stack );
  141. lua_settop( L, stack );
  142. i2c_config_t cfg;
  143. memset( &cfg, 0, sizeof( cfg ) );
  144. cfg.mode = I2C_MODE_SLAVE;
  145. lua_getfield( L, stack, "sda" );
  146. int sda = luaL_optint( L , -1, -1 );
  147. luaL_argcheck( L, GPIO_IS_VALID_OUTPUT_GPIO(sda), stack, "invalid sda pin" );
  148. cfg.sda_io_num = (gpio_num_t)sda;
  149. cfg.sda_pullup_en = GPIO_PULLUP_ENABLE;
  150. lua_getfield( L, stack, "scl" );
  151. int scl = luaL_optint( L , -1, -1 );
  152. luaL_argcheck( L, GPIO_IS_VALID_OUTPUT_GPIO(scl), stack, "invalid scl pin" );
  153. cfg.scl_io_num = (gpio_num_t)scl;
  154. cfg.scl_pullup_en = GPIO_PULLUP_ENABLE;
  155. lua_getfield( L, stack, "10bit" );
  156. bool en_10bit = luaL_optbool( L , -1, false );
  157. cfg.slave.addr_10bit_en = en_10bit ? 1 : 0;
  158. lua_getfield( L, stack, "addr" );
  159. int slave_addr = luaL_optint( L , -1, -1 );
  160. if (en_10bit)
  161. luaL_argcheck( L, slave_addr >= 0 && slave_addr < 1<<10, stack, "invalid slave address" );
  162. else
  163. luaL_argcheck( L, slave_addr >= 0 && slave_addr < 1<<7, stack, "invalid slave address" );
  164. cfg.slave.slave_addr = slave_addr;
  165. lua_getfield( L, stack, "rxbuf_len" );
  166. int rxbuf_len = luaL_optint( L , -1, I2C_SLAVE_DEFAULT_RXBUF_LEN );
  167. luaL_argcheck( L, rxbuf_len >= 0, stack, "invalid rxbuf_len" );
  168. ud->rxbuf_len = rxbuf_len;
  169. lua_getfield( L, stack, "txbuf_len" );
  170. int txbuf_len = luaL_optint( L , -1, I2C_SLAVE_DEFAULT_TXBUF_LEN );
  171. luaL_argcheck( L, rxbuf_len >= 0, stack, "invalid rxbuf_len" );
  172. i2c_lua_checkerr( L, i2c_param_config( port, &cfg ) );
  173. i2c_lua_checkerr( L, i2c_driver_install( port, cfg.mode, rxbuf_len, txbuf_len, 0 ));
  174. ud->receivedcb_ref = LUA_NOREF;
  175. if (!setup_rtos_task( ud, port )) {
  176. i2c_driver_delete( port );
  177. luaL_error( L, "rtos task creation failed" );
  178. }
  179. return 0;
  180. }
  181. // Write to slave send buffer
  182. //
  183. static int li2c_slave_send( lua_State *L )
  184. {
  185. get_udata(L);
  186. ud = ud;
  187. const char *pdata;
  188. size_t datalen, i;
  189. int numdata;
  190. uint8_t byte;
  191. uint32_t wrote = 0;
  192. unsigned argn;
  193. if( lua_gettop( L ) < 2 )
  194. return luaL_error( L, "wrong arg type" );
  195. for( argn = 2; argn <= lua_gettop( L ); argn ++ )
  196. {
  197. // lua_isnumber() would silently convert a string of digits to an integer
  198. // whereas here strings are handled separately.
  199. if( lua_type( L, argn ) == LUA_TNUMBER )
  200. {
  201. numdata = ( int )luaL_checkinteger( L, argn );
  202. if( numdata < 0 || numdata > 255 )
  203. return luaL_error( L, "wrong arg range" );
  204. byte = (uint8_t)numdata;
  205. if( i2c_slave_write_buffer( port, &byte, 1, portMAX_DELAY ) < 0 )
  206. break;
  207. wrote ++;
  208. }
  209. else if( lua_istable( L, argn ) )
  210. {
  211. datalen = lua_objlen( L, argn );
  212. for( i = 0; i < datalen; i ++ )
  213. {
  214. lua_rawgeti( L, argn, i + 1 );
  215. numdata = ( int )luaL_checkinteger( L, -1 );
  216. lua_pop( L, 1 );
  217. if( numdata < 0 || numdata > 255 )
  218. return luaL_error( L, "wrong arg range" );
  219. byte = (uint8_t)numdata;
  220. if( i2c_slave_write_buffer( port, &byte, 1, portMAX_DELAY ) < 0 )
  221. break;
  222. }
  223. wrote += i;
  224. if( i < datalen )
  225. break;
  226. }
  227. else
  228. {
  229. pdata = luaL_checklstring( L, argn, &datalen );
  230. if( i2c_slave_write_buffer( port, (uint8_t *)pdata, datalen, portMAX_DELAY ) < 0 )
  231. break;
  232. wrote += datalen;
  233. }
  234. }
  235. lua_pushinteger( L, wrote );
  236. return 1;
  237. }
  238. // Register or unregister an event callback handler
  239. //
  240. static int li2c_slave_on( lua_State *L )
  241. {
  242. enum events{
  243. ON_RECEIVE = 0
  244. };
  245. const char *const eventnames[] = {"receive", NULL};
  246. get_udata(L);
  247. int stack = 1;
  248. int event = luaL_checkoption(L, ++stack, NULL, eventnames);
  249. switch (event) {
  250. case ON_RECEIVE:
  251. luaL_unref( L, LUA_REGISTRYINDEX, ud->receivedcb_ref );
  252. ++stack;
  253. if (lua_isfunction( L, stack ) || lua_islightfunction( L, stack )) {
  254. lua_pushvalue( L, stack ); // copy argument (func) to the top of stack
  255. ud->receivedcb_ref = luaL_ref( L, LUA_REGISTRYINDEX );
  256. }
  257. break;
  258. default:
  259. break;
  260. }
  261. return 0;
  262. }
  263. const LUA_REG_TYPE li2c_slave_map[] = {
  264. { LSTRKEY( "on" ), LFUNCVAL( li2c_slave_on ) },
  265. { LSTRKEY( "setup" ), LFUNCVAL( li2c_slave_setup ) },
  266. { LSTRKEY( "send" ), LFUNCVAL( li2c_slave_send ) },
  267. { LNILKEY, LNILVAL }
  268. };
  269. void li2c_hw_slave_init( lua_State *L )
  270. {
  271. // prepare task id
  272. i2c_receive_task_id = task_get_id( i2c_receive_task );
  273. }